KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > config > Config


1 /* ************************************************************************** *
2  * Copyright (C) 2004 NightLabs GmbH, Marco Schulze *
3  * All rights reserved. *
4  * http://www.NightLabs.de *
5  * *
6  * This program and the accompanying materials are free software; you can re- *
7  * distribute it and/or modify it under the terms of the GNU General Public *
8  * License as published by the Free Software Foundation; either ver 2 of the *
9  * License, or any later version. *
10  * *
11  * This module is distributed in the hope that it will be useful, but WITHOUT *
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- *
13  * NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more *
14  * details. *
15  * *
16  * You should have received a copy of the GNU General Public License along *
17  * with this module; if not, write to the Free Software Foundation, Inc.: *
18  * 59 Temple Place, Suite 330 *
19  * Boston MA 02111-1307 *
20  * USA *
21  * *
22  * Or get it online: *
23  * http://www.opensource.org/licenses/gpl-license.php *
24  * *
25  * In case, you want to use this module or parts of it in a proprietary pro- *
26  * ject, you can purchase it under the NightLabs Commercial License. Please *
27  * contact NightLabs GmbH under info AT nightlabs DOT com for more infos or *
28  * visit http://www.NightLabs.com *
29  * ************************************************************************** */

30
31 package com.nightlabs.config;
32
33 import java.beans.XMLDecoder JavaDoc;
34 import java.beans.XMLEncoder JavaDoc;
35 import java.io.File JavaDoc;
36 import java.io.FileInputStream JavaDoc;
37 import java.io.FileOutputStream JavaDoc;
38 import java.io.IOException JavaDoc;
39 import java.io.InputStream JavaDoc;
40 import java.net.URL JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.Iterator JavaDoc;
45 import java.util.List JavaDoc;
46 import java.util.Map JavaDoc;
47
48 import org.apache.log4j.Level;
49 import org.apache.log4j.Logger;
50
51 import com.nightlabs.util.Utils;
52
53
54 /**
55  * The class <code>com.nightlabs.config.Config</code> is a manager for the
56  * plugins' config objects. Each plugin can register an own config-object,
57  * which will be serialized to and deserialized from a XML config file.
58  * See {@link com.nightlabs.config.ConfigModule} for an introduction how to
59  * set up a custom config object.
60  * <p>
61  * A plugins config-object is identified by its <code>Class</code> combined
62  * with a unique identifier for this class, wich can be <code>null</code>.
63  *
64  * @author Marco Schulze
65  * @author Marc Klinger - marc at nightlabs dot de
66  */

67 public class Config
68 {
69     public static Logger LOGGER = Logger.getLogger(Config.class.getName());
70
71   // =================================
72
// STATIC PROPERTIES
73
// =================================
74

75   /**
76    * The character used to append a unique identifier to a config file name in
77    * multi-file-mode.
78    */

79   public static final char beforeIdentifier = '-';
80
81   /**
82    * The character used to append a midfix to a config file name in
83    * multi-file-mode.
84    */

85   public static final char beforeMidfix = '-';
86
87   /**
88    * The character used to append the class name of the {@link ConfigModule}
89    * to a config file name in multi-file-mode.
90    */

91   public static final char beforeClassName = '-';
92
93   /**
94    * The shared instance
95    */

96   private static Config sharedInstance;
97
98   /**
99    * Indicates whether we use multi-file-mode or not
100    *
101    * @see #createSharedInstance(String configFile, boolean loadConfFile, String configDir, boolean multiFileMode)
102    */

103   private boolean multiFileMode;
104
105   /**
106    * Castor writes "UTF-8" as encoding in the XML-file, thus we must make sure,
107    * the writers and readers use this encoding.
108    */

109   public static final String JavaDoc ENCODING = "UTF-8";
110
111
112   // =================================
113
// STATIC METHODS
114
// =================================
115

116   /**
117    * @return <code>true</code> if we have already created a shared instance.
118    * @see #sharedInstance()
119    */

120   public static boolean isConfigExisting()
121   {
122     return sharedInstance != null;
123   }
124
125   /**
126    * Creates the shared instance with the given parameters.
127    *
128    * @param configFile A relative filename. This name is used as name for the
129    * base config file and used to generate the include file names
130    * in multi-file-mode.
131    * @param loadConfFile Indicates wether or not to load the file contents now.
132    * @param configDir Where to look for the config files.
133    * @param multiFileMode Wether to use multi-file-mode or not.
134    * @return The newly created shared instance.
135    * @throws ConfigException if creation of config object fails.
136    * @see #sharedInstance()
137    *
138    * @deprecated Because the single file mode reduces the functionality and the stability of the Config, you should
139    * not use this method anymore.
140    * @see #createSharedInstance(String configFile, boolean loadConfFile, String configDir)
141    */

142   public static Config createSharedInstance(String JavaDoc configFile, boolean loadConfFile, String JavaDoc configDir, boolean multiFileMode)
143   throws ConfigException
144   {
145     sharedInstance = new Config(configFile, loadConfFile, configDir, multiFileMode);
146
147     return sharedInstance;
148   }
149
150   /**
151    * Creates the shared instance of Config (in multi file mode) with the given parameters.
152    *
153    * @param configFile A relative filename. This name is used as name for the
154    * base config file and used to generate the include file names
155    * in multi-file-mode.
156    * @param loadConfFile Indicates wether or not to load the file contents now.
157    * @param configDir Where to look for the config files.
158    * @return The newly created shared instance.
159    * @throws ConfigException if creation of config object fails.
160    * @see #sharedInstance()
161    */

162   public static Config createSharedInstance(String JavaDoc configFile, boolean loadConfFile, String JavaDoc configDir)
163   throws ConfigException
164   {
165     sharedInstance = new Config(configFile, loadConfFile, configDir);
166
167     return sharedInstance;
168   }
169
170   /**
171    * Get the shared instance.
172    *
173    * @param throwExceptionIfNotExisting Indicates whether or not to throw an
174    * exception if shared instance does not yet exist.
175    * @return The shared config instance or <code>null</code> if <code>throwExceptionIfNotExisting</code>
176    * is <code>false</code> and the shared instance does not yet exist.
177    * @throws IllegalStateException If <code>throwExceptionIfNotExisting</code>
178    * is <code>true</code> and the shared instance does not yet exist.
179    */

180   public static Config sharedInstance(boolean throwExceptionIfNotExisting)
181   {
182     if (sharedInstance==null && throwExceptionIfNotExisting)
183       throw new IllegalStateException JavaDoc("Shared instance if Config was not yet created! You have to execute createSharedInstance() before using sharedInstance()!");
184
185     return sharedInstance;
186   }
187
188   /**
189    * Get the shared instance. This is a convenience method for
190    * <code>sharedInstance(true)</code>.
191    *
192    * @return The shared config instance.
193    * @throws IllegalStateException If the shared instance does not yet exist.
194    */

195   public static Config sharedInstance()
196   {
197     return sharedInstance(true);
198   }
199
200
201   // =================================
202
// PRIVATE PROPERTIES
203
// =================================
204

205
206   /**
207    * Base directory for configuration files.
208    */

209   private String JavaDoc configDir;
210
211   /**
212    * The filename for the basic config file. All include config file names
213    * are also created using this property.
214    */

215   private String JavaDoc configFilename;
216
217   /**
218    * These objects get read from and written to the xml-config file via Castor.
219    * Each server-plugin can register a config plugin via <code>putConfigModule()</code>.
220    */

221   private HashMap JavaDoc configModules = new HashMap JavaDoc();
222
223   /**
224    * Key: String relativeCfModFileName<br/>
225    * Value: ConfigModule cfMod
226    */

227   private HashMap JavaDoc includedCfModsByFileName = new HashMap JavaDoc();
228
229   /**
230    * Key: ConfigModule cfMod<br/>
231    * Value: String relativeCfModFileName
232    */

233   private HashMap JavaDoc includedCfModsByCfMod = new HashMap JavaDoc();
234
235   /**
236    * This Set is used to remember wich config modules have been
237    * created lazily for a user request.
238    * <p>
239    * These config modules won't be added to the config includes
240    * in multi-file-mode if they have not changed and thus are not
241    * written to disk.
242    * <p>
243    * The instance of the Set itself will be created lazily in
244    * multi-file-mode when needed.
245    */

246   private HashSet JavaDoc _lazyConfigModules = null;
247
248   protected boolean isLazyConfigModule(ConfigModule cfMod)
249   {
250     if (_lazyConfigModules == null)
251         return false;
252
253     boolean res = _lazyConfigModules.contains(getConfigModuleIdentifyingName(cfMod));
254     return res;
255   }
256
257   protected void registerLazyConfigModule(ConfigModule cfMod)
258   {
259     if (_lazyConfigModules == null)
260         _lazyConfigModules = new HashSet JavaDoc();
261
262     _lazyConfigModules.add(getConfigModuleIdentifyingName(cfMod));
263   }
264
265   // =================================
266
// CONSTRUCTORS
267
// =================================
268

269   /**
270    * Create a config object using an <code>InputStream</code> as source.
271    *
272    * @param configStream The stream to read the config from.
273    * @throws ConfigException If something fails.
274    */

275   public Config(InputStream JavaDoc configStream)
276   throws ConfigException
277   {
278     this.multiFileMode = false;
279     this.readFromInputStream(configStream);
280   }
281   
282   public Config(String JavaDoc configFile, boolean loadConfFile, String JavaDoc configDir)
283   throws ConfigException
284   {
285     this(configFile, loadConfFile, configDir, true);
286   }
287
288   /**
289    * Creates a config object with the given parameters.
290
291    * @param configFile A relative filename. This name is used as name for the
292    * base config file and used to generate the include file names
293    * in multi-file-mode.
294    * @param loadConfFile Indicates wether or not to load the file contents now.
295    * @param configDir Where to look for the config files.
296    * @param multiFileMode Wether to use multi-file-mode or not.
297    *
298    * @throws ConfigException if creation of config object fails.
299    * @see #createSharedInstance(String configFile, boolean loadConfFile, String configDir, boolean multiFileMode)
300    * @see #sharedInstance()
301    * @see #Config(String configFile, boolean loadConfFile, String configDir)
302    *
303    * @deprecated You should never use multiFileMode=false, because this reduces functionality and stability!
304    */

305   public Config(String JavaDoc configFile, boolean loadConfFile, String JavaDoc configDir, boolean multiFileMode)
306   throws ConfigException
307   {
308     try {
309       this.multiFileMode = multiFileMode;
310
311       /**
312        * Because the framework can be used with different application-plugins,
313        * we give configDir as parameter. Application parameters are given to the
314        * app as array parameter of the main method.
315        */

316       this.setConfigDir(configDir);
317       configDir = this.configDir;
318
319       LOGGER.log(Level.INFO, "ProgRootDir = \""+this.configDir+"\"");
320
321       if (configFile == null || "".equals(configFile))
322         configFile = configDir + "config.xml";
323       else {
324   // if (configFile.indexOf(File.separator)<0)
325
// configFile = configDir + configFile;
326

327         File JavaDoc cf = new File JavaDoc(configFile);
328         if (! cf.isAbsolute())
329           cf = new File JavaDoc(configDir + configFile);
330
331         configFile = cf.getCanonicalPath();
332       }
333
334       this.configFilename = configFile;
335
336       LOGGER.log(Level.INFO, "ConfigFile = \""+this.configFilename+"\"");
337
338       if (loadConfFile)
339         this.loadConfFile();
340     } catch (ConfigException x) {
341       throw x;
342     } catch (Exception JavaDoc x) {
343       throw new ConfigException(x);
344     }
345   }
346
347
348   // =================================
349
// ACCESSOR METHODS
350
// =================================
351

352   /**
353    * Accessor method for property @link{#configFilename},
354    * the filename for the basic config file. All include config file names
355    * are also created using this property.
356    * @return The @link{#configFilename}
357    */

358   public String JavaDoc getConfigFilename()
359   {
360     return configFilename;
361   }
362
363   /**
364    * Accessor method for property {@link #configFilename},
365    * the filename for the basic config file. All include config file names
366    * are also created using this property.
367    * @param configFilename The new value.
368    */

369   public void setConfigFilename(String JavaDoc configFilename)
370   {
371     this.configFilename = configFilename;
372   }
373
374   public String JavaDoc getConfigDir()
375   {
376     return this.configDir;
377   }
378
379   public void setConfigDir(String JavaDoc _configDir)
380     throws ConfigException
381   {
382     File JavaDoc fcfdir = new File JavaDoc(_configDir);
383     try {
384             this.configDir = Utils.addFinalSlash(fcfdir.getCanonicalPath());
385         } catch (IOException JavaDoc e) {
386             throw new ConfigException(e);
387         }
388   }
389
390 // public String getDataDir()
391
// {
392
// return Utils.addFinalSlash(this.configDir + "Data");
393
// }
394

395
396   // =================================
397
// METHODS
398
// =================================
399

400   /**
401    * Load the config from file without using a midfix.
402    *
403    * @throws ConfigException if loading the config fails.
404    * @see #loadConfFile(String includeFileMidfix)
405    */

406   public void loadConfFile()
407   throws ConfigException
408   {
409     loadConfFile(null);
410   }
411
412   /**
413    * The method <code>loadConfFile()</code> loads all sub configs that are
414    * in the config file into the hash map @link{#configModules}.
415    * <p>
416    * In multi-file-mode included config modules are read from their own files
417    * using <code>includeFileMidfix</code> if not null.
418    *
419    * @param includeFileMidfix The file midfix to use. This is used by language
420    * config sub-system. If <code>includeFileMidfix</code> is <code>null</code>,
421    * no midfixes are used.
422    * @throws ConfigException if loading the config fails.
423    */

424   public void loadConfFile(String JavaDoc includeFileMidfix)
425   throws ConfigException
426   {
427     try {
428       File JavaDoc cf = new File JavaDoc(configFilename);
429       if (!cf.exists()) {
430         this.configModules.clear();
431         return;
432       }
433
434       FileInputStream JavaDoc fin = new FileInputStream JavaDoc(cf);
435
436       readFromInputStream(fin);
437
438       if (multiFileMode) {
439         ConfigIncludes configIncludes = (ConfigIncludes)getConfigModule(ConfigIncludes.class, false);
440
441         if (configIncludes == null) {
442           configIncludes = new ConfigIncludes();
443           configIncludes._setConfig(this);
444           configIncludes.init();
445           putConfigModule(configIncludes);
446         } // if (configIncludes == null) {
447

448         // iterate all config includes
449
for (Iterator JavaDoc iterator = configIncludes.getConfigIncludes().iterator(); iterator.hasNext(); ) {
450           ConfigInclude configInclude = (ConfigInclude)iterator.next();
451           String JavaDoc relativeIncludeFileNameOrg = configInclude.getIncludeFile();
452           String JavaDoc relativeIncludeFileNameWithMidfix = createIncludeFileName(
453               relativeIncludeFileNameOrg,
454               null,
455               includeFileMidfix);
456
457           try {
458
459             // assumed location of config module include file on disk
460
File JavaDoc includeFile = new File JavaDoc(configDir, relativeIncludeFileNameWithMidfix);
461
462             if(!includeFile.exists()) {
463               URL JavaDoc url = null;
464               // search in package path
465
if(configInclude.getSearchClass() != null) {
466                 url = Class.forName(configInclude.getSearchClass()).
467                     getResource(
468                     relativeIncludeFileNameWithMidfix);
469               }
470               if(url == null) {
471                 // search in config modules resources
472
url = Class.forName(configInclude.getIncludeClass()).
473                     getResource(
474                     relativeIncludeFileNameWithMidfix);
475                 if (url == null) {
476                   // The resource can not be assigned, thus we don't have any
477
// serialized configuration.
478
throw new ConfigException("Configuration file "
479                                             + relativeIncludeFileNameWithMidfix + " cannot be found. File does not exist in ConfigDir or class resource directory.");
480                 }
481               }
482               includeFile = new File JavaDoc(url.getFile());
483             }
484
485             // read include file from input stream
486
fin = new FileInputStream JavaDoc(includeFile);
487             try {
488     // InputStreamReader isReader = new InputStreamReader(fin, ENCODING);
489

490     // Unmarshaller unMarshaller = new Unmarshaller(ObjectEnvelope.class); //, com.nightlabs.plugin.PluginMan.getClassLoader());
491
// ObjectEnvelope objEnv = (ObjectEnvelope)unMarshaller.unmarshal(isReader);
492
ConfigModule cfMod;
493                 XMLDecoder JavaDoc d = new XMLDecoder JavaDoc(fin);
494                 try {
495                     cfMod = (ConfigModule)d.readObject();
496                     cfMod.setChanged(false);
497                 } finally {
498                     d.close();
499                 }
500
501                 // get deserialized config module, call init() and add it to local lists.
502
// ConfigModule cfMod = (ConfigModule)objEnv.getObject();
503
cfMod._setConfig(this);
504                 cfMod.init();
505                 this.putIncludedCfMod(relativeIncludeFileNameWithMidfix, cfMod);
506                 this.configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod);
507                 
508             } finally {
509                 fin.close();
510             }
511
512           } catch (Exception JavaDoc x) {
513             LOGGER.log(
514                     Level.WARN,
515                                 "Unable to load config module file: "+relativeIncludeFileNameWithMidfix,
516                                 x);
517           }
518
519         } // for (Iterator itCfIncs = configIncludes.getConfigIncludeFiles().iterator(); itCfIncs.hasNext(); ) {
520
} // if (multiFileMode) {
521

522     } catch (ConfigException x) {
523       throw x;
524     } catch (Exception JavaDoc x) {
525       throw new ConfigException(x);
526     }
527   }
528
529   /**
530    * This method calls <tt>saveConfFile(String includeFileMidfix, boolean forceSaveAllModules)</tt>
531    * with <tt>includeFileMidFix=null</tt> and <tt>forceSaveAllModules=false</tt>.
532    *
533    * @throws ConfigException
534    *
535    * @see #saveConfFile(String, boolean)
536    */

537   public void saveConfFile()
538   throws ConfigException
539   {
540     saveConfFile(null, false);
541   }
542   
543   /**
544    * This method calls <tt>saveConfFile(String includeFileMidfix, boolean forceSaveAllModules)</tt>
545    * with <tt>includeFileMidFix=null</tt>.
546    *
547    * @throws ConfigException
548    *
549    * @see #saveConfFile(String, boolean)
550    */

551   public void saveConfFile(boolean forceSaveAllModules)
552   throws ConfigException
553   {
554     saveConfFile(null, forceSaveAllModules);
555   }
556   
557   protected Object JavaDoc saveMutex = new Object JavaDoc();
558   
559   /**
560    * This method calls <tt>saveConfFile(String includeFileMidfix, boolean forceSaveAllModules)</tt>
561    * with <tt>forceSaveAllModules=false</tt>.
562    *
563    * @throws ConfigException
564    *
565    * @see #saveConfFile(String, boolean)
566    */

567   public void saveConfFile(String JavaDoc includeFileMidfix)
568   throws ConfigException
569   {
570     saveConfFile(includeFileMidfix, false);
571   }
572
573   /**
574    * This method writes all via <code>putConfigModule()</code> registered ConfigModules into
575    * the configuration XML-file.
576    * <p>
577    * First, it creates a temporary file (with the
578    * extension ".new") and replaces the real config by this one after the
579    * config could be successfully serialized. This avoids to crash the config
580    * file if the marshaller throws an exception.
581    *
582    * @param includeFileMidfix The midfix <code>String</code> to distinguish
583    * different versions of the same configuration module as used
584    * in language configuration.
585    * <p>If <code>includeFileMidfix</code> is <code>null</code>, no
586    * midfix will be used (standard behaviour).
587    * @param forceSaveAllModules Normally, only config modules that are marked as changed
588    * are written to disk. If forceSaveAllModules is true, all config modules
589    * are saved and the changed flag is ignored.
590    */

591   public void saveConfFile(String JavaDoc includeFileMidfix, boolean forceSaveAllModules)
592   throws ConfigException
593   {
594     synchronized (saveMutex) {
595         LOGGER.info("Saving config with includeFileMidfix=\""+includeFileMidfix+"\"");
596         try {
597           List JavaDoc internalConfigModules = new ArrayList JavaDoc(this.configModules.size());
598     
599           ConfigIncludes configIncludes = null;
600     
601           if (multiFileMode) {
602             // get the config modules responsable for included config modules
603
configIncludes = (ConfigIncludes)getConfigModule(ConfigIncludes.class, false);
604             if (configIncludes == null) {
605               // if we don't have config includes create them and add them this config
606
configIncludes = new ConfigIncludes();
607               configIncludes._setConfig(this);
608               configIncludes.init();
609               putConfigModule(configIncludes);
610             }
611             else {
612               // if we have an old set of include files, clear it
613
configIncludes.getConfigIncludes().clear();
614             }
615           }
616     
617           // This map is used to save changed config modules (all modules that must
618
// be written in multi file mode due to a change) to avoid multiple calls
619
// of _isChanged().
620
HashMap JavaDoc changedIncludedConfigModules = new HashMap JavaDoc();
621     
622           //
623
//
624
//
625
for (Iterator JavaDoc it = configModules.entrySet().iterator(); it.hasNext(); ) {
626             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
627             ConfigModule cfMod = (ConfigModule)entry.getValue();
628     
629             String JavaDoc relativeCfIncFileName = getIncludedCfModFileName(cfMod);
630             ConfigInclude cfInc = new ConfigInclude(
631               cfMod, relativeCfIncFileName
632             );
633     
634             if(!multiFileMode || relativeCfIncFileName == null) {
635               // inline config modules
636
internalConfigModules.add(cfMod);
637             }
638             else {
639               /** @todo nicht hinzu wenn nicht geaendert und nicht aus file gelesen */
640               if(!isLazyConfigModule(cfMod) || cfMod._isChanged() || forceSaveAllModules)
641                 configIncludes.getConfigIncludes().add(new ConfigInclude(cfMod, relativeCfIncFileName));
642               if(cfMod._isChanged() || forceSaveAllModules) {
643                 // external changed config modules
644
// if(!configIncludes.getConfigIncludes().contains()
645
changedIncludedConfigModules.put(relativeCfIncFileName, includedCfModsByFileName.get(relativeCfIncFileName));
646               }
647             }
648           } // for (Iterator it = configModules.entrySet().iterator(); it.hasNext(); ) {
649

650     
651           // write inline configuration vector to temporary file
652
String JavaDoc tmpCf = configFilename+".new";
653     
654           FileOutputStream JavaDoc fout = new FileOutputStream JavaDoc(tmpCf);
655     
656     // OutputStreamWriter osWriter = new OutputStreamWriter(fout, ENCODING);
657
// Marshaller marshaller = new Marshaller( osWriter );
658
// marshaller.marshal(new ListEnvelope(internalConfigModules));
659
XMLEncoder JavaDoc e = new XMLEncoder JavaDoc(fout);
660           e.writeObject(internalConfigModules);
661           e.close();
662     
663           fout.close();
664     
665     // // Zeilenumbr�che einf�gen
666
// String srcFile = tmpCf;
667
// tmpCf = configFilename+".new_format";
668
// XMLFormatter.formatXMLFile(srcFile, tmpCf, " ");
669
// File sf = new File(srcFile);
670
// sf.delete();
671

672           //
673
// write all include files that have changed to temporary files.
674
//
675
if(!changedIncludedConfigModules.isEmpty()) {
676             for (Iterator JavaDoc it = changedIncludedConfigModules.entrySet().iterator(); it.hasNext(); ) {
677               Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
678               String JavaDoc includedConfigModuleFilename = (String JavaDoc) entry.getKey();
679               ConfigModule includedConfigModule = (ConfigModule) entry.getValue();
680               
681               LOGGER.debug("waiting for readLock of configModule \"" + includedConfigModuleFilename + "\"...");
682               includedConfigModule.acquireReadLock();
683               try {
684                 LOGGER.debug("got readLock of configModule \"" + includedConfigModuleFilename + "\". Opening file...");
685         
686                   File JavaDoc tmpCfModFile = new File JavaDoc(configDir,
687                                                includedConfigModuleFilename + ".new");
688     
689                   fout = new FileOutputStream JavaDoc(tmpCfModFile);
690         // osWriter = new OutputStreamWriter(fout, ENCODING);
691
// marshaller = new Marshaller(osWriter);
692
// marshaller.marshal(new ObjectEnvelope(includedConfigModule));
693
e = new XMLEncoder JavaDoc(fout);
694                   
695                   LOGGER.debug("opened file for configModule \"" + includedConfigModuleFilename + "\". writing object...");
696                   e.writeObject(includedConfigModule);
697                   includedConfigModule.setChanged(false);
698                   e.close();
699                   fout.close();
700                   
701                   LOGGER.debug("configModule \"" + includedConfigModuleFilename + "\" written.");
702               } finally {
703                 includedConfigModule.releaseLock();
704               }
705               LOGGER.debug("read lock of configModule \"" + includedConfigModuleFilename + "\" released.");
706     
707     // // Zeilenumbr�che einf�gen
708
// String cfModSrcFile = tmpCfModFile.getCanonicalPath();
709
// tmpCfModFile = new File(configDir,
710
// includedConfigModuleFilename + ".new_format");
711
// XMLFormatter.formatXMLFile(cfModSrcFile, tmpCfModFile.getCanonicalPath(), " ");
712
// sf = new File(cfModSrcFile);
713
// sf.delete();
714
} // for (Iterator it = changedIncludedConfigModules.entrySet().iterator(); it.hasNext(); ) {
715
}
716     
717     
718           // copy new base config file over old
719
File JavaDoc of = new File JavaDoc(configFilename);
720           of.delete();
721           File JavaDoc nf = new File JavaDoc(tmpCf);
722           nf.renameTo(of);
723     
724           // copy all changed include config files
725
if(!changedIncludedConfigModules.isEmpty()) {
726             for (Iterator JavaDoc it = changedIncludedConfigModules.keySet().iterator();
727                  it.hasNext(); ) {
728               String JavaDoc includedConfigModuleFilename = (String JavaDoc) it.next();
729     
730               File JavaDoc tmpCfModFile = new File JavaDoc(configDir,
731                     includedConfigModuleFilename +
732                     ".new");
733                                            //".new_format");
734
File JavaDoc cfModFile = new File JavaDoc(configDir, includedConfigModuleFilename);
735               cfModFile.delete();
736               tmpCfModFile.renameTo(cfModFile);
737             } // for (Iterator it = changedIncludedConfigModules.entrySet().iterator(); it.hasNext(); ) {
738
}
739     
740         } catch (Exception JavaDoc x) {
741           throw new ConfigException(x);
742         }
743     } // synchronized (saveMutex) {
744
}
745
746
747   // =================================
748
// CONFIG MODULE MAMAGEMENT PROPERTIES
749
// =================================
750

751   /**
752    * If one instance of the type <code>configModuleClass</code> is registered,
753    * it will be returned. Otherwise the result of this method will be
754    * <code>null</code>. If you set <code>throwExceptionIfNotExistent = true</code>
755    * a ConfigModuleNotFoundException will be thrown
756    * instead of returning <code>null</code>.
757    *
758    * @return The registered ConfigModule or <code>null</code> if no ConfigModule
759    * could be found.
760    * @see #getCreateConfigModule(Class configModuleClass)
761    */

762   public ConfigModule getConfigModule(Class JavaDoc configModuleClass, boolean throwExceptionIfNotExistent)
763   {
764     return getConfigModule(configModuleClass.getName(), throwExceptionIfNotExistent);
765   }
766
767   public ConfigModule getConfigModule(Class JavaDoc configModuleClass, String JavaDoc identifier, boolean throwExceptionIfNotExistent)
768   {
769     return getConfigModule(configModuleClass.getName(), identifier, throwExceptionIfNotExistent);
770   }
771
772   /**
773    * If one instance of the type <code>configModuleClass</code> is registered,
774    * it will be returned. Otherwise this method will throw
775    * a ConfigModuleNotFoundException.
776    *
777    * @see #getCreateConfigModule(Class configModuleClass)
778    * @return The registered ConfigModule.
779    */

780   public ConfigModule getConfigModule(Class JavaDoc configModuleClass)
781   {
782     return getConfigModule(configModuleClass.getName());
783   }
784
785   /**
786    * @deprecated Use createConfigModule(...) instead!
787    * @see #createConfigModule(Class configModuleClass)
788    */

789   public ConfigModule getCreateConfigModule(Class JavaDoc configModuleClass)
790   throws ConfigException
791   {
792     return getCreateConfigModule(configModuleClass, null);
793   }
794   
795   /**
796    * This method creates an instance of the given ConfigModule or returns
797    * an existing one that has been previously created.
798    *
799    * @param configModuleClass
800    * @return The requested ConfigModule
801    * @throws ConfigException
802    * @see #createConfigModule(Class configModuleClass, String identifier)
803    */

804   public ConfigModule createConfigModule(Class JavaDoc configModuleClass)
805   throws ConfigException
806   {
807     return createConfigModule(configModuleClass, null);
808   }
809   
810   /**
811    * @deprecated Use createConfigModule(...) instead!
812    * @see #createConfigModule(Class configModuleClass, String identifier)
813    */

814   public ConfigModule getCreateConfigModule(Class JavaDoc configModuleClass, String JavaDoc identifier)
815   throws ConfigException
816     {
817     return createConfigModule(configModuleClass, identifier);
818     }
819
820   /**
821    * Does the same as <code>getConfigModule(Class configModuleClass)</code>, but
822    * this method will never return null, but create an instance of the given class.
823    * If the instance does already exist, it will return the existing instance.
824    *
825    * A plugins config-object is identified by its <code>Class</code> combined
826    * with a unique identifier for this class, wich can be <code>null</code>.
827    *
828    * @see #getConfigModule(Class configModuleClass)
829    */

830   public ConfigModule createConfigModule(Class JavaDoc configModuleClass, String JavaDoc identifier)
831   throws ConfigException
832   {
833     try {
834       ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClass, identifier));
835       if (cfMod == null) {
836         cfMod = (ConfigModule)configModuleClass.newInstance();
837         cfMod._setConfig(this);
838         cfMod.setIdentifier(identifier);
839         cfMod.init();
840         configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod);
841         registerLazyConfigModule(cfMod);
842       }
843
844       if (multiFileMode) {
845         StringBuffer JavaDoc sbPrefix = new StringBuffer JavaDoc(configFilename);
846         int lastSlashPos = sbPrefix.lastIndexOf(File.separator);
847         sbPrefix.delete(0, lastSlashPos + 1);
848         int lastDotPos = sbPrefix.lastIndexOf(".");
849         String JavaDoc suffix = sbPrefix.substring(lastDotPos);
850         sbPrefix.delete(lastDotPos, sbPrefix.length());
851
852
853         putIncludedCfMod(
854           sbPrefix.toString()+beforeClassName+
855           //configModuleClass.getName()+ //
856
getConfigModuleIdentifyingName(cfMod)+
857           suffix,
858           cfMod
859         );
860       } // if (multiFileMode) {
861

862       return cfMod;
863     } catch (Throwable JavaDoc t) {
864       throw new ConfigException(t);
865     }
866   }
867
868
869   /**
870    * This method does exactly the same as the overloaded version with a Class parameter.
871    * It returns an
872    * instance of the desired type, but the type is a string parameter representing
873    * the fully-qualified name.
874    * @see #getConfigModule(Class configModuleClass)
875    */

876   public ConfigModule getConfigModule(String JavaDoc configModuleClassName)
877   {
878     return getConfigModule(configModuleClassName, null);
879   }
880   public ConfigModule getConfigModule(String JavaDoc configModuleClassName, String JavaDoc identifier)
881   {
882     ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClassName, identifier));
883     if (cfMod == null)
884       throw new ConfigModuleNotFoundException("No ConfigModule of type \""+configModuleClassName+"\" existent!");
885     return cfMod;
886   }
887   public ConfigModule getConfigModule(String JavaDoc configModuleClassName, boolean throwExceptionIfNotExistent)
888   {
889     return getConfigModule(configModuleClassName, null, throwExceptionIfNotExistent);
890   }
891   public ConfigModule getConfigModule(String JavaDoc configModuleClassName, String JavaDoc identifier, boolean throwExceptionIfNotExistent)
892   {
893     ConfigModule cfMod = (ConfigModule)configModules.get(getConfigModuleIdentifyingName(configModuleClassName, identifier));
894     if (cfMod == null && throwExceptionIfNotExistent)
895       throw new ConfigModuleNotFoundException("No ConfigModule of type \""+configModuleClassName+"\" existent!");
896     return cfMod;
897   }
898
899   /**
900    * Registers an instance of a config module. If one instance of the same type
901    * and identifier already exists, it will be replaced by the new one.
902    */

903   public void putConfigModule(ConfigModule configModule)
904   {
905     String JavaDoc cfModFileName = getIncludedCfModFileName(configModule);
906     if (cfModFileName != null) {
907       includedCfModsByFileName.remove(cfModFileName);
908       includedCfModsByCfMod.remove(configModule);
909     } // if (cfModFileName != null) {
910

911     configModules.put(getConfigModuleIdentifyingName(configModule), configModule);
912   }
913
914
915   // =======================================
916
// PRIVATE HELPING METHODS
917
// =======================================
918
private void readFromInputStream(InputStream JavaDoc fin)
919   throws ConfigException
920   {
921     try {
922 // InputStreamReader isReader = new InputStreamReader(fin, ENCODING);
923
// Unmarshaller unMarshaller = new Unmarshaller(ListEnvelope.class); // , com.nightlabs.plugin.PluginMan.getClassLoader());
924
// ListEnvelope env = (ListEnvelope)unMarshaller.unmarshal(isReader);
925
XMLDecoder JavaDoc d = new XMLDecoder JavaDoc(fin);
926         List JavaDoc ls = (List JavaDoc)d.readObject();
927         d.close();
928
929       fin.close();
930
931 // List ls = env.getList();
932
// if (ls == null)
933
// ls = new Vector();
934

935       this.configModules.clear();
936
937       Iterator JavaDoc it = ls.iterator();
938       while (it.hasNext()) {
939         ConfigModule cfMod = (ConfigModule)it.next();
940         cfMod._setConfig(this);
941         cfMod.init();
942         this.configModules.put(getConfigModuleIdentifyingName(cfMod), cfMod);
943       }
944     } catch (Exception JavaDoc x) {
945       throw new ConfigException(x);
946     }
947   }
948
949   protected void putIncludedCfMod(String JavaDoc relativeCfModFileName, ConfigModule cfMod)
950   {
951     includedCfModsByFileName.put(relativeCfModFileName, cfMod);
952     includedCfModsByCfMod.put(cfMod, relativeCfModFileName);
953   }
954   protected ConfigModule getIncludedCfMod(String JavaDoc relativeCfModFileName)
955   {
956     return (ConfigModule)includedCfModsByFileName.get(relativeCfModFileName);
957   }
958   protected String JavaDoc getIncludedCfModFileName(ConfigModule cfMod)
959   {
960     return (String JavaDoc)includedCfModsByCfMod.get(cfMod);
961   }
962
963   private static String JavaDoc createIncludeFileName(String JavaDoc orgFileName, String JavaDoc identifier, String JavaDoc midfix)
964   {
965     boolean haveIdentifier = identifier != null && !identifier.equals("");
966     boolean haveMidfix = midfix != null && !midfix.equals("");
967
968     if(!haveMidfix && !haveIdentifier)
969       return orgFileName;
970
971     StringBuffer JavaDoc sb = new StringBuffer JavaDoc(orgFileName);
972     int lastDotPos = sb.lastIndexOf(".");
973     String JavaDoc ext;
974     if(lastDotPos != -1) {
975       ext = sb.substring(lastDotPos);
976       sb.delete(lastDotPos, sb.length());
977     } else {
978       ext = "";
979     }
980
981 // int lastDCPos = sb.lastIndexOf("#");
982
// if (lastDCPos >= 0)
983
// sb.delete(lastDCPos, sb.length());
984

985     if(haveIdentifier) {
986       sb.append(beforeIdentifier);
987       sb.append(identifier);
988       sb.append(ext);
989     }
990
991     if(haveMidfix) {
992       sb.append(beforeMidfix);
993       sb.append(midfix);
994       sb.append(ext);
995     }
996
997     return sb.toString();
998   }
999
1000  private static String JavaDoc getConfigModuleIdentifyingName(ConfigModule module)
1001  {
1002    return getConfigModuleIdentifyingName(module.getClass(), module.getIdentifier());
1003  }
1004  private static String JavaDoc getConfigModuleIdentifyingName(Class JavaDoc moduleClass, String JavaDoc identifier)
1005  {
1006    return getConfigModuleIdentifyingName(moduleClass.getName(), identifier);
1007  }
1008  private static String JavaDoc getConfigModuleIdentifyingName(String JavaDoc moduleClassName, String JavaDoc identifier)
1009  {
1010    StringBuffer JavaDoc result = new StringBuffer JavaDoc(moduleClassName);
1011    if(identifier != null && !identifier.equals("")) {
1012      result.append(beforeIdentifier);
1013      result.append(identifier);
1014    }
1015    return result.toString();
1016  }
1017
1018}
Popular Tags