View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   // CatalogManager.java - Access CatalogManager.properties
6   
7   /*
8    * Copyright 2001-2004 The Apache Software Foundation or its licensors,
9    * as applicable.
10   *
11   * Licensed under the Apache License, Version 2.0 (the "License");
12   * you may not use this file except in compliance with the License.
13   * You may obtain a copy of the License at
14   *
15   *      http://www.apache.org/licenses/LICENSE-2.0
16   *
17   * Unless required by applicable law or agreed to in writing, software
18   * distributed under the License is distributed on an "AS IS" BASIS,
19   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   * See the License for the specific language governing permissions and
21   * limitations under the License.
22   */
23  
24  package com.sun.org.apache.xml.internal.resolver;
25  
26  import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
27  import com.sun.org.apache.xml.internal.resolver.helpers.BootstrapResolver;
28  import com.sun.org.apache.xml.internal.resolver.helpers.Debug;
29  import java.io.InputStream;
30  import java.net.MalformedURLException;
31  import java.net.URL;
32  import java.util.MissingResourceException;
33  import java.util.PropertyResourceBundle;
34  import java.util.ResourceBundle;
35  import java.util.StringTokenizer;
36  import java.util.Vector;
37  import sun.reflect.misc.ReflectUtil;
38  
39  /**
40   * CatalogManager provides an interface to the catalog properties.
41   *
42   * <p>Properties can come from two places: from system properties or
43   * from a <i>CatalogManager.properties</i> file. This class provides a transparent
44   * interface to both, with system properties preferred over property file values.</p>
45   *
46   * <p>The following table summarizes the properties:</p>
47   *
48   * <table border="1">
49   * <thead>
50   * <tr>
51   * <td>System Property</td>
52   * <td>CatalogManager.properties<br/>Property</td>
53   * <td>Description</td>
54   * </tr>
55   * </thead>
56   * <tbody>
57   * <tr>
58   * <td>xml.catalog.ignoreMissing</td>
59   * <td>&#160;</td>
60   * <td>If true, a missing <i>CatalogManager.properties</i> file or missing properties
61   * within that file will not generate warning messages. See also the
62   * <i>ignoreMissingProperties</i> method.</td>
63   * </tr>
64   *
65   * <tr>
66   * <td>xml.catalog.files</td>
67   * <td>catalogs</td>
68   * <td>The <emph>semicolon-delimited</emph> list of catalog files.</td>
69   * </tr>
70   *
71   * <tr>
72   * <td>&#160;</td>
73   * <td>relative-catalogs</td>
74   * <td>If false, relative catalog URIs are made absolute with respect to the base URI of
75   * the <i>CatalogManager.properties</i> file. This setting only applies to catalog
76   * URIs obtained from the <i>catalogs</i> property <emph>in the</emph>
77   * <i>CatalogManager.properties</i> file</td>
78   * </tr>
79   *
80   * <tr>
81   * <td>xml.catalog.verbosity</td>
82   * <td>verbosity</td>
83   * <td>If non-zero, the Catalog classes will print informative and debugging messages.
84   * The higher the number, the more messages.</td>
85   * </tr>
86   *
87   * <tr>
88   * <td>xml.catalog.prefer</td>
89   * <td>prefer</td>
90   * <td>Which identifier is preferred, "public" or "system"?</td>
91   * </tr>
92   *
93   * <tr>
94   * <td>xml.catalog.staticCatalog</td>
95   * <td>static-catalog</td>
96   * <td>Should a single catalog be constructed for all parsing, or should a different
97   * catalog be created for each parser?</td>
98   * </tr>
99   *
100  * <tr>
101  * <td>xml.catalog.allowPI</td>
102  * <td>allow-oasis-xml-catalog-pi</td>
103  * <td>If the source document contains "oasis-xml-catalog" processing instructions,
104  * should they be used?</td>
105  * </tr>
106  *
107  * <tr>
108  * <td>xml.catalog.className</td>
109  * <td>catalog-class-name</td>
110  * <td>If you're using the convenience classes
111  * <tt>com.sun.org.apache.xml.internal.resolver.tools.*</tt>), this setting
112  * allows you to specify an alternate class name to use for the underlying
113  * catalog.</td>
114  * </tr>
115  * </tbody>
116  * </table>
117  *
118  * @see Catalog
119  *
120  * @author Norman Walsh
121  * <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
122  *
123  * @version 1.0
124  */
125 
126 public class CatalogManager {
127   private static String pFiles         = "xml.catalog.files";
128   private static String pVerbosity     = "xml.catalog.verbosity";
129   private static String pPrefer        = "xml.catalog.prefer";
130   private static String pStatic        = "xml.catalog.staticCatalog";
131   private static String pAllowPI       = "xml.catalog.allowPI";
132   private static String pClassname     = "xml.catalog.className";
133   private static String pIgnoreMissing = "xml.catalog.ignoreMissing";
134 
135   /** A static CatalogManager instance for sharing */
136   private static CatalogManager staticManager = new CatalogManager();
137 
138   /** The bootstrap resolver to use when loading XML Catalogs. */
139   private BootstrapResolver bResolver = new BootstrapResolver();
140 
141   /** Flag to ignore missing property files and/or properties */
142   private boolean ignoreMissingProperties
143     = (SecuritySupport.getSystemProperty(pIgnoreMissing) != null
144        || SecuritySupport.getSystemProperty(pFiles) != null);
145 
146   /** Holds the resources after they are loaded from the file. */
147   private ResourceBundle resources;
148 
149   /** The name of the CatalogManager properties file. */
150   private String propertyFile = "CatalogManager.properties";
151 
152   /** The location of the propertyFile */
153   private URL propertyFileURI = null;
154 
155   /** Default catalog files list. */
156   private String defaultCatalogFiles = "./xcatalog";
157 
158   /** Current catalog files list. */
159   private String catalogFiles = null;
160 
161   /** Did the catalogFiles come from the properties file? */
162   private boolean fromPropertiesFile = false;
163 
164   /** Default verbosity level if there is no property setting for it. */
165   private int defaultVerbosity = 1;
166 
167   /** Current verbosity level. */
168   private Integer verbosity = null;
169 
170   /** Default preference setting. */
171   private boolean defaultPreferPublic = true;
172 
173   /** Current preference setting. */
174   private Boolean preferPublic = null;
175 
176   /** Default setting of the static catalog flag. */
177   private boolean defaultUseStaticCatalog = true;
178 
179   /** Current setting of the static catalog flag. */
180   private Boolean useStaticCatalog = null;
181 
182   /** The static catalog used by this manager. */
183   private static Catalog staticCatalog = null;
184 
185   /** Default setting of the oasisXMLCatalogPI flag. */
186   private boolean defaultOasisXMLCatalogPI = true;
187 
188   /** Current setting of the oasisXMLCatalogPI flag. */
189   private Boolean oasisXMLCatalogPI = null;
190 
191   /** Default setting of the relativeCatalogs flag. */
192   private boolean defaultRelativeCatalogs = true;
193 
194   /** Current setting of the relativeCatalogs flag. */
195   private Boolean relativeCatalogs = null;
196 
197   /** Current catalog class name. */
198   private String catalogClassName = null;
199     /**
200      * Indicates whether implementation parts should use
201      *   service loader (or similar).
202      * Note the default value (false) is the safe option..
203      */
204     private boolean useServicesMechanism;
205 
206   /** The manager's debug object. Used for printing debugging messages.
207    *
208    * <p>This field is public so that objects that have access to this
209    * CatalogManager can use this debug object.</p>
210    */
211   public Debug debug = null;
212 
213   /** Constructor. */
214   public CatalogManager() {
215     init();
216   }
217 
218   /** Constructor that specifies an explicit property file. */
219   public CatalogManager(String propertyFile) {
220     this.propertyFile = propertyFile;
221     init();
222   }
223 
224   private void init() {
225     debug = new Debug();
226     // Note that we don't setDebug() here; we do that lazily. Either the
227     // user will set it explicitly, or we'll do it automagically if they
228     // read from the propertyFile for some other reason. That way, there's
229     // no attempt to read from the file before the caller has had a chance
230     // to avoid it.
231     if (System.getSecurityManager() == null) {
232         useServicesMechanism = true;
233     }
234   }
235   /** Set the bootstrap resolver.*/
236   public void setBootstrapResolver(BootstrapResolver resolver) {
237     bResolver = resolver;
238   }
239 
240   /** Get the bootstrap resolver.*/
241   public BootstrapResolver getBootstrapResolver() {
242     return bResolver;
243   }
244 
245   /**
246    * Load the properties from the propertyFile and build the
247    * resources from it.
248    */
249   private synchronized void readProperties() {
250     try {
251       propertyFileURI = CatalogManager.class.getResource("/"+propertyFile);
252       InputStream in =
253         CatalogManager.class.getResourceAsStream("/"+propertyFile);
254       if (in==null) {
255         if (!ignoreMissingProperties) {
256           System.err.println("Cannot find "+propertyFile);
257           // there's no reason to give this warning more than once
258           ignoreMissingProperties = true;
259         }
260         return;
261       }
262       resources = new PropertyResourceBundle(in);
263     } catch (MissingResourceException mre) {
264       if (!ignoreMissingProperties) {
265         System.err.println("Cannot read "+propertyFile);
266       }
267     } catch (java.io.IOException e) {
268       if (!ignoreMissingProperties) {
269         System.err.println("Failure trying to read "+propertyFile);
270       }
271     }
272 
273     // This is a bit of a hack. After we've successfully read the properties,
274     // use them to set the default debug level, if the user hasn't already set
275     // the default debug level.
276     if (verbosity == null) {
277       try {
278         String verbStr = resources.getString("verbosity");
279         int verb = Integer.parseInt(verbStr.trim());
280         debug.setDebug(verb);
281         verbosity = new Integer(verb);
282       } catch (Exception e) {
283         // nop
284       }
285     }
286   }
287 
288   /**
289    * Allow access to the static CatalogManager
290    */
291   public static CatalogManager getStaticManager() {
292     return staticManager;
293   }
294 
295   /**
296    * How are missing properties handled?
297    *
298    * <p>If true, missing or unreadable property files will
299    * not be reported. Otherwise, a message will be sent to System.err.
300    * </p>
301    */
302   public boolean getIgnoreMissingProperties() {
303     return ignoreMissingProperties;
304   }
305 
306   /**
307    * How should missing properties be handled?
308    *
309    * <p>If ignore is true, missing or unreadable property files will
310    * not be reported. Otherwise, a message will be sent to System.err.
311    * </p>
312    */
313   public void setIgnoreMissingProperties(boolean ignore) {
314     ignoreMissingProperties = ignore;
315   }
316 
317   /**
318    * How are missing properties handled?
319    *
320    * <p>If ignore is true, missing or unreadable property files will
321    * not be reported. Otherwise, a message will be sent to System.err.
322    * </p>
323    *
324    * @deprecated No longer static; use get/set methods.
325    */
326   public void ignoreMissingProperties(boolean ignore) {
327     setIgnoreMissingProperties(ignore);
328   }
329 
330   /**
331    * Obtain the verbosity setting from the properties.
332    *
333    * @return The verbosity level from the propertyFile or the
334    * defaultVerbosity.
335    */
336   private int queryVerbosity () {
337     String defaultVerbStr = Integer.toString(defaultVerbosity);
338 
339     String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
340 
341     if (verbStr == null) {
342       if (resources==null) readProperties();
343       if (resources != null) {
344         try {
345           verbStr = resources.getString("verbosity");
346         } catch (MissingResourceException e) {
347           verbStr = defaultVerbStr;
348         }
349       } else {
350         verbStr = defaultVerbStr;
351       }
352     }
353 
354     int verb = defaultVerbosity;
355 
356     try {
357       verb = Integer.parseInt(verbStr.trim());
358     } catch (Exception e) {
359       System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
360     }
361 
362     // This is a bit of a hack. After we've successfully got the verbosity,
363     // we have to use it to set the default debug level,
364     // if the user hasn't already set the default debug level.
365     if (verbosity == null) {
366       debug.setDebug(verb);
367       verbosity = new Integer(verb);
368     }
369 
370     return verb;
371   }
372 
373   /**
374    * What is the current verbosity?
375    */
376   public int getVerbosity() {
377     if (verbosity == null) {
378       verbosity = new Integer(queryVerbosity());
379     }
380 
381     return verbosity.intValue();
382   }
383 
384   /**
385    * Set the current verbosity.
386    */
387   public void setVerbosity (int verbosity) {
388     this.verbosity = new Integer(verbosity);
389     debug.setDebug(verbosity);
390   }
391 
392   /**
393    * What is the current verbosity?
394    *
395    * @deprecated No longer static; use get/set methods.
396    */
397   public int verbosity () {
398     return getVerbosity();
399   }
400 
401   /**
402    * Obtain the relativeCatalogs setting from the properties.
403    *
404    * @return The relativeCatalogs setting from the propertyFile or the
405    * defaultRelativeCatalogs.
406    */
407   private boolean queryRelativeCatalogs () {
408     if (resources==null) readProperties();
409 
410     if (resources==null) return defaultRelativeCatalogs;
411 
412     try {
413       String allow = resources.getString("relative-catalogs");
414       return (allow.equalsIgnoreCase("true")
415               || allow.equalsIgnoreCase("yes")
416               || allow.equalsIgnoreCase("1"));
417     } catch (MissingResourceException e) {
418       return defaultRelativeCatalogs;
419     }
420   }
421 
422   /**
423    * Get the relativeCatalogs setting.
424    *
425    * <p>This property is used when the catalogFiles property is
426    * interrogated. If true, then relative catalog entry file names
427    * are returned. If false, relative catalog entry file names are
428    * made absolute with respect to the properties file before returning
429    * them.</p>
430    *
431    * <p>This property <emph>only applies</emph> when the catalog files
432    * come from a properties file. If they come from a system property or
433    * the default list, they are never considered relative. (What would
434    * they be relative to?)</p>
435    *
436    * <p>In the properties, a value of 'yes', 'true', or '1' is considered
437    * true, anything else is false.</p>
438    *
439    * @return The relativeCatalogs setting from the propertyFile or the
440    * defaultRelativeCatalogs.
441    */
442   public boolean getRelativeCatalogs () {
443     if (relativeCatalogs == null) {
444       relativeCatalogs = new Boolean(queryRelativeCatalogs());
445     }
446 
447     return relativeCatalogs.booleanValue();
448   }
449 
450   /**
451    * Set the relativeCatalogs setting.
452    *
453    * @see #getRelativeCatalogs()
454    */
455   public void setRelativeCatalogs (boolean relative) {
456     relativeCatalogs = new Boolean(relative);
457   }
458 
459   /**
460    * Get the relativeCatalogs setting.
461    *
462    * @deprecated No longer static; use get/set methods.
463    */
464   public boolean relativeCatalogs () {
465     return getRelativeCatalogs();
466   }
467 
468   /**
469    * Obtain the list of catalog files from the properties.
470    *
471    * @return A semicolon delimited list of catlog file URIs
472    */
473   private String queryCatalogFiles () {
474     String catalogList = SecuritySupport.getSystemProperty(pFiles);
475     fromPropertiesFile = false;
476 
477     if (catalogList == null) {
478       if (resources == null) readProperties();
479       if (resources != null) {
480         try {
481           catalogList = resources.getString("catalogs");
482           fromPropertiesFile = true;
483         } catch (MissingResourceException e) {
484           System.err.println(propertyFile + ": catalogs not found.");
485           catalogList = null;
486         }
487       }
488     }
489 
490     if (catalogList == null) {
491       catalogList = defaultCatalogFiles;
492     }
493 
494     return catalogList;
495   }
496 
497   /**
498    * Return the current list of catalog files.
499    *
500    * @return A vector of the catalog file names or null if no catalogs
501    * are available in the properties.
502    */
503   public Vector getCatalogFiles() {
504     if (catalogFiles == null) {
505       catalogFiles = queryCatalogFiles();
506     }
507 
508     StringTokenizer files = new StringTokenizer(catalogFiles, ";");
509     Vector catalogs = new Vector();
510     while (files.hasMoreTokens()) {
511       String catalogFile = files.nextToken();
512       URL absURI = null;
513 
514       if (fromPropertiesFile && !relativeCatalogs()) {
515         try {
516           absURI = new URL(propertyFileURI, catalogFile);
517           catalogFile = absURI.toString();
518         } catch (MalformedURLException mue) {
519           absURI = null;
520         }
521       }
522 
523       catalogs.add(catalogFile);
524     }
525 
526     return catalogs;
527   }
528 
529   /**
530    * Set the list of catalog files.
531    */
532   public void setCatalogFiles(String fileList) {
533     catalogFiles = fileList;
534     fromPropertiesFile = false;
535   }
536 
537   /**
538    * Return the current list of catalog files.
539    *
540    * @return A vector of the catalog file names or null if no catalogs
541    * are available in the properties.
542    *
543    * @deprecated No longer static; use get/set methods.
544    */
545   public Vector catalogFiles() {
546     return getCatalogFiles();
547   }
548 
549   /**
550    * Obtain the preferPublic setting from the properties.
551    *
552    * <p>In the properties, a value of 'public' is true,
553    * anything else is false.</p>
554    *
555    * @return True if prefer is public or the
556    * defaultPreferSetting.
557    */
558   private boolean queryPreferPublic () {
559     String prefer = SecuritySupport.getSystemProperty(pPrefer);
560 
561     if (prefer == null) {
562       if (resources==null) readProperties();
563       if (resources==null) return defaultPreferPublic;
564       try {
565         prefer = resources.getString("prefer");
566       } catch (MissingResourceException e) {
567         return defaultPreferPublic;
568       }
569     }
570 
571     if (prefer == null) {
572       return defaultPreferPublic;
573     }
574 
575     return (prefer.equalsIgnoreCase("public"));
576   }
577 
578   /**
579    * Return the current prefer public setting.
580    *
581    * @return True if public identifiers are preferred.
582    */
583   public boolean getPreferPublic () {
584     if (preferPublic == null) {
585       preferPublic = new Boolean(queryPreferPublic());
586     }
587     return preferPublic.booleanValue();
588   }
589 
590   /**
591    * Set the prefer public setting.
592    */
593   public void setPreferPublic (boolean preferPublic) {
594     this.preferPublic = new Boolean(preferPublic);
595   }
596 
597   /**
598    * Return the current prefer public setting.
599    *
600    * @return True if public identifiers are preferred.
601    *
602    * @deprecated No longer static; use get/set methods.
603    */
604   public boolean preferPublic () {
605     return getPreferPublic();
606   }
607 
608   /**
609    * Obtain the static-catalog setting from the properties.
610    *
611    * <p>In the properties, a value of 'yes', 'true', or '1' is considered
612    * true, anything else is false.</p>
613    *
614    * @return The static-catalog setting from the propertyFile or the
615    * defaultUseStaticCatalog.
616    */
617   private boolean queryUseStaticCatalog () {
618     String staticCatalog = SecuritySupport.getSystemProperty(pStatic);
619 
620     if (staticCatalog == null) {
621       if (resources==null) readProperties();
622       if (resources==null) return defaultUseStaticCatalog;
623       try {
624         staticCatalog = resources.getString("static-catalog");
625       } catch (MissingResourceException e) {
626         return defaultUseStaticCatalog;
627       }
628     }
629 
630     if (staticCatalog == null) {
631       return defaultUseStaticCatalog;
632     }
633 
634     return (staticCatalog.equalsIgnoreCase("true")
635             || staticCatalog.equalsIgnoreCase("yes")
636             || staticCatalog.equalsIgnoreCase("1"));
637   }
638 
639   /**
640    * Get the current use static catalog setting.
641    */
642   public boolean getUseStaticCatalog() {
643     if (useStaticCatalog == null) {
644       useStaticCatalog = new Boolean(queryUseStaticCatalog());
645     }
646 
647     return useStaticCatalog.booleanValue();
648   }
649 
650   /**
651    * Set the use static catalog setting.
652    */
653   public void setUseStaticCatalog(boolean useStatic) {
654     useStaticCatalog = new Boolean(useStatic);
655   }
656 
657   /**
658    * Get the current use static catalog setting.
659    *
660    * @deprecated No longer static; use get/set methods.
661    */
662   public boolean staticCatalog() {
663     return getUseStaticCatalog();
664   }
665 
666   /**
667    * Get a new catalog instance.
668    *
669    * This method always returns a new instance of the underlying catalog class.
670    */
671   public Catalog getPrivateCatalog() {
672     Catalog catalog = staticCatalog;
673 
674     if (useStaticCatalog == null) {
675       useStaticCatalog = new Boolean(getUseStaticCatalog());
676     }
677 
678     if (catalog == null || !useStaticCatalog.booleanValue()) {
679 
680       try {
681         String catalogClassName = getCatalogClassName();
682 
683         if (catalogClassName == null) {
684           catalog = new Catalog();
685         } else {
686           try {
687             catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance();
688           } catch (ClassNotFoundException cnfe) {
689             debug.message(1,"Catalog class named '"
690                           + catalogClassName
691                           + "' could not be found. Using default.");
692             catalog = new Catalog();
693           } catch (ClassCastException cnfe) {
694             debug.message(1,"Class named '"
695                           + catalogClassName
696                           + "' is not a Catalog. Using default.");
697             catalog = new Catalog();
698           }
699         }
700 
701         catalog.setCatalogManager(this);
702         catalog.setupReaders();
703         catalog.loadSystemCatalogs();
704       } catch (Exception ex) {
705         ex.printStackTrace();
706       }
707 
708       if (useStaticCatalog.booleanValue()) {
709         staticCatalog = catalog;
710       }
711     }
712 
713     return catalog;
714   }
715 
716   /**
717    * Get a catalog instance.
718    *
719    * If this manager uses static catalogs, the same static catalog will
720    * always be returned. Otherwise a new catalog will be returned.
721    */
722   public Catalog getCatalog() {
723     Catalog catalog = staticCatalog;
724 
725     if (useStaticCatalog == null) {
726       useStaticCatalog = new Boolean(getUseStaticCatalog());
727     }
728 
729     if (catalog == null || !useStaticCatalog.booleanValue()) {
730       catalog = getPrivateCatalog();
731       if (useStaticCatalog.booleanValue()) {
732         staticCatalog = catalog;
733       }
734     }
735 
736     return catalog;
737   }
738 
739   /**
740    * <p>Obtain the oasisXMLCatalogPI setting from the properties.</p>
741    *
742    * <p>In the properties, a value of 'yes', 'true', or '1' is considered
743    * true, anything else is false.</p>
744    *
745    * @return The oasisXMLCatalogPI setting from the propertyFile or the
746    * defaultOasisXMLCatalogPI.
747    */
748   public boolean queryAllowOasisXMLCatalogPI () {
749     String allow = SecuritySupport.getSystemProperty(pAllowPI);
750 
751     if (allow == null) {
752       if (resources==null) readProperties();
753       if (resources==null) return defaultOasisXMLCatalogPI;
754       try {
755         allow = resources.getString("allow-oasis-xml-catalog-pi");
756       } catch (MissingResourceException e) {
757         return defaultOasisXMLCatalogPI;
758       }
759     }
760 
761     if (allow == null) {
762       return defaultOasisXMLCatalogPI;
763     }
764 
765     return (allow.equalsIgnoreCase("true")
766             || allow.equalsIgnoreCase("yes")
767             || allow.equalsIgnoreCase("1"));
768   }
769 
770   /**
771    * Get the current XML Catalog PI setting.
772    */
773   public boolean getAllowOasisXMLCatalogPI () {
774     if (oasisXMLCatalogPI == null) {
775       oasisXMLCatalogPI = new Boolean(queryAllowOasisXMLCatalogPI());
776     }
777 
778     return oasisXMLCatalogPI.booleanValue();
779   }
780 
781   public boolean useServicesMechanism() {
782       return useServicesMechanism;
783   }
784   /**
785    * Set the XML Catalog PI setting
786    */
787   public void setAllowOasisXMLCatalogPI(boolean allowPI) {
788     oasisXMLCatalogPI = new Boolean(allowPI);
789   }
790 
791   /**
792    * Get the current XML Catalog PI setting.
793    *
794    * @deprecated No longer static; use get/set methods.
795    */
796   public boolean allowOasisXMLCatalogPI() {
797     return getAllowOasisXMLCatalogPI();
798   }
799 
800   /**
801    * Obtain the Catalog class name setting from the properties.
802    *
803    */
804   public String queryCatalogClassName () {
805     String className = SecuritySupport.getSystemProperty(pClassname);
806 
807     if (className == null) {
808       if (resources==null) readProperties();
809       if (resources==null) return null;
810       try {
811         return resources.getString("catalog-class-name");
812       } catch (MissingResourceException e) {
813         return null;
814       }
815     }
816 
817     return className;
818   }
819 
820   /**
821    * Get the current Catalog class name.
822    */
823   public String getCatalogClassName() {
824     if (catalogClassName == null) {
825       catalogClassName = queryCatalogClassName();
826     }
827 
828     return catalogClassName;
829   }
830 
831   /**
832    * Set the Catalog class name.
833    */
834   public void setCatalogClassName(String className) {
835     catalogClassName = className;
836   }
837 
838   /**
839    * Get the current Catalog class name.
840    *
841    * @deprecated No longer static; use get/set methods.
842    */
843   public String catalogClassName() {
844     return getCatalogClassName();
845   }
846 }