KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > configuration > CmsConfigurationManager


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/configuration/CmsConfigurationManager.java,v $
3  * Date : $Date: 2006/03/27 14:52:46 $
4  * Version: $Revision: 1.30 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.configuration;
33
34 import org.opencms.i18n.CmsEncoder;
35 import org.opencms.main.CmsLog;
36 import org.opencms.util.CmsFileUtil;
37 import org.opencms.xml.CmsXmlEntityResolver;
38 import org.opencms.xml.CmsXmlErrorHandler;
39
40 import java.io.File JavaDoc;
41 import java.io.FileOutputStream JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.io.OutputStream JavaDoc;
44 import java.net.URL JavaDoc;
45 import java.text.SimpleDateFormat JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.Date JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50 import java.util.Map JavaDoc;
51
52 import org.apache.commons.digester.Digester;
53 import org.apache.commons.logging.Log;
54
55 import org.dom4j.Document;
56 import org.dom4j.DocumentHelper;
57 import org.dom4j.Element;
58 import org.dom4j.dom.DOMDocumentType;
59 import org.dom4j.io.OutputFormat;
60 import org.dom4j.io.XMLWriter;
61 import org.xml.sax.SAXException JavaDoc;
62
63 /**
64  * Configuration manager for digesting the OpenCms XML configuration.<p>
65  *
66  * Reads the individual configuration class nodes first and creaes new
67  * instances of the "base" configuration classes.<p>
68  *
69  * @author Alexander Kandzior
70  *
71  * @version $Revision: 1.30 $
72  *
73  * @since 6.0.0
74  */

75 public class CmsConfigurationManager implements I_CmsXmlConfiguration {
76
77     /** The location of the OpenCms configuration DTD if the default prefix is the system ID. */
78     public static final String JavaDoc DEFAULT_DTD_LOCATION = "org/opencms/configuration/";
79
80     /** The default prefix for the OpenCms configuration DTD. */
81     public static final String JavaDoc DEFAULT_DTD_PREFIX = "http://www.opencms.org/dtd/6.0/";
82
83     /** The name of the default XML file for this configuration. */
84     public static final String JavaDoc DEFAULT_XML_FILE_NAME = "opencms.xml";
85
86     /** The name of the DTD file for this configuration. */
87     public static final String JavaDoc DTD_FILE_NAME = "opencms-configuration.dtd";
88
89     /** The "opencms" root node of the XML configuration. */
90     public static final String JavaDoc N_ROOT = "opencms";
91
92     /** Postfix for original configuration files. */
93     public static final String JavaDoc POSTFIX_ORI = ".ori";
94
95     /** The config node. */
96     protected static final String JavaDoc N_CONFIG = "config";
97
98     /** The configurations node. */
99     protected static final String JavaDoc N_CONFIGURATION = "configuration";
100
101     /** Date format for the backup file time prefix. */
102     private static final SimpleDateFormat JavaDoc BACKUP_DATE_FORMAT = new SimpleDateFormat JavaDoc("yyyy-MM-dd_HH-mm-ss_");
103
104     /** The log object for this class. */
105     private static final Log LOG = CmsLog.getLog(CmsConfigurationManager.class);
106
107     /** The number of days to keep old backups for. */
108     private static final long MAX_BACKUP_DAYS = 15;
109
110     /** The folder where to store the backup files of the configuration. */
111     private File JavaDoc m_backupFolder;
112
113     /** The base folder where the configuration files are located. */
114     private File JavaDoc m_baseFolder;
115
116     /** The initialized configuration classes. */
117     private List JavaDoc m_configurations;
118
119     /** The digester for reading the XML configuration. */
120     private Digester m_digester;
121
122     /** The legacy configuration based on "opencms.properties". */
123     private Map JavaDoc m_legacyConfiguration;
124
125     /**
126      * Creates a new OpenCms configuration manager.<p>
127      *
128      * @param baseFolder base folder where XML configurations to load are located
129      */

130     public CmsConfigurationManager(String JavaDoc baseFolder) {
131
132         m_baseFolder = new File JavaDoc(baseFolder);
133         if (!m_baseFolder.exists()) {
134             if (LOG.isErrorEnabled()) {
135                 LOG.error(Messages.get().getBundle().key(
136                     Messages.LOG_INVALID_CONFIG_BASE_FOLDER_1,
137                     m_baseFolder.getAbsolutePath()));
138             }
139         }
140         m_backupFolder = new File JavaDoc(m_baseFolder.getAbsolutePath() + File.separatorChar + "backup");
141         if (!m_backupFolder.exists()) {
142             if (LOG.isDebugEnabled()) {
143                 LOG.debug(Messages.get().getBundle().key(
144                     Messages.LOG_CREATE_CONFIG_BKP_FOLDER_1,
145                     m_backupFolder.getAbsolutePath()));
146             }
147             m_backupFolder.mkdirs();
148         }
149         if (LOG.isDebugEnabled()) {
150             LOG.debug(Messages.get().getBundle().key(Messages.LOG_CONFIG_BASE_FOLDER_1, m_baseFolder.getAbsolutePath()));
151             LOG.debug(Messages.get().getBundle().key(Messages.LOG_CONFIG_BKP_FOLDER_1, m_backupFolder.getAbsolutePath()));
152         }
153         cacheDtdSystemId(this);
154         m_configurations = new ArrayList JavaDoc();
155     }
156
157     /**
158      * Adds a configuration object to the configuration manager.<p>
159      *
160      * @param configuration the configuration to add
161      */

162     public void addConfiguration(I_CmsXmlConfiguration configuration) {
163
164         if (LOG.isDebugEnabled()) {
165             LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_CONFIG_1, configuration));
166         }
167         m_configurations.add(configuration);
168         cacheDtdSystemId(configuration);
169     }
170
171     /**
172      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String)
173      */

174     public void addConfigurationParameter(String JavaDoc paramName, String JavaDoc paramValue) {
175
176         // noop, this configuration has no additional parameters
177
}
178
179     /**
180      * @see org.opencms.configuration.I_CmsXmlConfiguration#addXmlDigesterRules(org.apache.commons.digester.Digester)
181      */

182     public void addXmlDigesterRules(Digester digester) {
183
184         // add rule for <configuration> node
185
digester.addObjectCreate(
186             "*/" + N_CONFIGURATION + "/" + N_CONFIG,
187             I_CmsXmlConfiguration.A_CLASS,
188             CmsConfigurationException.class);
189         digester.addSetNext("*/" + N_CONFIGURATION + "/" + N_CONFIG, "addConfiguration");
190     }
191
192     /**
193      * @see org.opencms.configuration.I_CmsXmlConfiguration#generateXml(org.dom4j.Element)
194      */

195     public Element generateXml(Element parent) {
196
197         // add the <configuration> node
198
Element configurationElement = parent.addElement(N_CONFIGURATION);
199         for (int i = 0; i < m_configurations.size(); i++) {
200             // append the individual configuration
201
I_CmsXmlConfiguration configuration = (I_CmsXmlConfiguration)m_configurations.get(i);
202             configurationElement.addElement(N_CONFIG).addAttribute(
203                 I_CmsXmlConfiguration.A_CLASS,
204                 configuration.getClass().getName());
205         }
206         return parent;
207     }
208
209     /**
210      * Creates the XML document build from the provided configuration.<p>
211      *
212      * @param configuration the configuration to build the XML for
213      * @return the XML document build from the provided configuration
214      */

215     public Document generateXml(I_CmsXmlConfiguration configuration) {
216
217         // create a new document
218
Document result = DocumentHelper.createDocument();
219
220         // set the document type
221
DOMDocumentType docType = new DOMDocumentType();
222         docType.setElementName(N_ROOT);
223         docType.setSystemID(configuration.getDtdUrlPrefix() + configuration.getDtdFilename());
224         result.setDocType(docType);
225
226         Element root = result.addElement(N_ROOT);
227         // start the XML generation
228
configuration.generateXml(root);
229
230         // return the resulting document
231
return result;
232     }
233
234     /**
235      * Returns the backup folder.<p>
236      *
237      * @return the backup folder
238      */

239     public File JavaDoc getBackupFolder() {
240
241         return m_backupFolder;
242     }
243
244     /**
245      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration()
246      */

247     public Map JavaDoc getConfiguration() {
248
249         return m_legacyConfiguration;
250     }
251
252     /**
253      * Returns a specific configuration from the list of initialized configurations.<p>
254      *
255      * @param clazz the configuration class that should be returned
256      * @return the initialized configuration class instance, or <code>null</code> if this is not found
257      */

258     public I_CmsXmlConfiguration getConfiguration(Class JavaDoc clazz) {
259
260         for (int i = 0; i < m_configurations.size(); i++) {
261             I_CmsXmlConfiguration configuration = (I_CmsXmlConfiguration)m_configurations.get(i);
262             if (clazz.equals(configuration.getClass())) {
263                 return configuration;
264             }
265         }
266         return null;
267     }
268
269     /**
270      * Returns the list of all initialized configurations.<p>
271      *
272      * @return the list of all initialized configurations
273      */

274     public List JavaDoc getConfigurations() {
275
276         return m_configurations;
277     }
278
279     /**
280      * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdFilename()
281      */

282     public String JavaDoc getDtdFilename() {
283
284         return DTD_FILE_NAME;
285     }
286
287     /**
288      * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdSystemLocation()
289      */

290     public String JavaDoc getDtdSystemLocation() {
291
292         return DEFAULT_DTD_LOCATION;
293     }
294
295     /**
296      * @see org.opencms.configuration.I_CmsXmlConfiguration#getDtdUrlPrefix()
297      */

298     public String JavaDoc getDtdUrlPrefix() {
299
300         return DEFAULT_DTD_PREFIX;
301     }
302
303     /**
304      * @see org.opencms.configuration.I_CmsXmlConfiguration#getXmlFileName()
305      */

306     public String JavaDoc getXmlFileName() {
307
308         return DEFAULT_XML_FILE_NAME;
309     }
310
311     /**
312      * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration()
313      */

314     public void initConfiguration() {
315
316         // does not need to be initialized
317
if (LOG.isDebugEnabled()) {
318             LOG.debug(Messages.get().getBundle().key(Messages.LOG_INIT_CONFIGURATION_1, this));
319         }
320     }
321
322     /**
323      * Loads the OpenCms configuration from the given XML file.<p>
324      *
325      * @throws SAXException in case of XML parse errors
326      * @throws IOException in case of file IO errors
327      */

328     public void loadXmlConfiguration() throws SAXException JavaDoc, IOException JavaDoc {
329
330         URL JavaDoc baseUrl = m_baseFolder.toURL();
331         if (LOG.isDebugEnabled()) {
332             LOG.debug(Messages.get().getBundle().key(Messages.LOG_BASE_URL_1, baseUrl));
333         }
334
335         // first load the base configuration
336
loadXmlConfiguration(baseUrl, this);
337
338         // now iterate all sub-configrations
339
Iterator JavaDoc i = m_configurations.iterator();
340         while (i.hasNext()) {
341             I_CmsXmlConfiguration config = (I_CmsXmlConfiguration)i.next();
342             loadXmlConfiguration(baseUrl, config);
343         }
344
345         // remove the old backups
346
removeOldBackups(MAX_BACKUP_DAYS);
347     }
348
349     /**
350      * Sets the configuration read from the legacy "opencms.properties".<p>
351      *
352      * @param legacyConfiguration the configuration read from the legacy "opencms.properties"
353      */

354     public void setConfiguration(Map JavaDoc legacyConfiguration) {
355
356         m_legacyConfiguration = legacyConfiguration;
357     }
358
359     /**
360      * Writes the XML configuration for the provided configuration instance.<p>
361      *
362      * @param clazz the configuration class to write the XML for
363      * @throws IOException in case of I/O errors while writing
364      * @throws CmsConfigurationException if the given class is not a valid configuration class
365      */

366     public void writeConfiguration(Class JavaDoc clazz) throws IOException JavaDoc, CmsConfigurationException {
367
368         I_CmsXmlConfiguration configuration = getConfiguration(clazz);
369         if (configuration == null) {
370             throw new CmsConfigurationException(Messages.get().container(
371                 Messages.ERR_CONFIG_WITH_UNKNOWN_CLASS_1,
372                 clazz.getName()));
373         }
374
375         // generate the file URL for the XML input
376
File JavaDoc file = new File JavaDoc(m_baseFolder, configuration.getXmlFileName());
377         if (LOG.isDebugEnabled()) {
378             LOG.debug(Messages.get().getBundle().key(Messages.LOG_WRITE_CONFIG_XMLFILE_1, file.getAbsolutePath()));
379         }
380
381         // generate the XML document
382
Document config = generateXml(configuration);
383
384         // output the document
385
XMLWriter writer = null;
386         OutputFormat format = OutputFormat.createPrettyPrint();
387         format.setIndentSize(4);
388         format.setTrimText(false);
389         format.setEncoding(CmsEncoder.ENCODING_UTF_8);
390
391         try {
392             OutputStream JavaDoc out = new FileOutputStream JavaDoc(file);
393             writer = new XMLWriter(out, format);
394             writer.write(config);
395             writer.flush();
396         } finally {
397             if (writer != null) {
398                 writer.close();
399             }
400         }
401
402         if (LOG.isInfoEnabled()) {
403             LOG.info(Messages.get().getBundle().key(
404                 Messages.LOG_WRITE_CONFIG_SUCCESS_2,
405                 file.getAbsolutePath(),
406                 configuration.getClass().getName()));
407         }
408     }
409
410     /**
411      * Creates a backup of the given XML configurations input file.<p>
412      *
413      * @param configuration the configuration for which the input file should be backed up
414      */

415     private void backupXmlConfiguration(I_CmsXmlConfiguration configuration) {
416
417         String JavaDoc fromName = m_baseFolder.getAbsolutePath() + File.separatorChar + configuration.getXmlFileName();
418         String JavaDoc toDatePrefix = BACKUP_DATE_FORMAT.format(new Date JavaDoc());
419         String JavaDoc toName = m_backupFolder.getAbsolutePath()
420             + File.separatorChar
421             + toDatePrefix
422             + configuration.getXmlFileName();
423
424         if (LOG.isDebugEnabled()) {
425             LOG.debug(Messages.get().getBundle().key(Messages.LOG_CREATE_CONFIG_BKP_2, fromName, toName));
426         }
427
428         try {
429             CmsFileUtil.copy(fromName, toName);
430         } catch (IOException JavaDoc e) {
431             LOG.error(Messages.get().getBundle().key(Messages.LOG_CREATE_CONFIG_BKP_FAILURE_1, toName), e);
432         }
433     }
434
435     /**
436      * Adds a new DTD system id prefix mapping for internal resolution of external URLs.<p>
437      *
438      * @param configuration the configuration to add the mapping from
439      */

440     private void cacheDtdSystemId(I_CmsXmlConfiguration configuration) {
441
442         if (configuration.getDtdSystemLocation() != null) {
443             try {
444                 String JavaDoc file = CmsFileUtil.readFile(configuration.getDtdSystemLocation()
445                     + configuration.getDtdFilename(), CmsEncoder.ENCODING_UTF_8);
446                 CmsXmlEntityResolver.cacheSystemId(
447                     configuration.getDtdUrlPrefix() + configuration.getDtdFilename(),
448                     file.getBytes(CmsEncoder.ENCODING_UTF_8));
449                 if (LOG.isDebugEnabled()) {
450                     LOG.debug(Messages.get().getBundle().key(
451                         Messages.LOG_CACHE_DTD_SYSTEM_ID_1,
452                         configuration.getDtdUrlPrefix()
453                             + configuration.getDtdFilename()
454                             + " --> "
455                             + configuration.getDtdSystemLocation()
456                             + configuration.getDtdFilename()));
457                 }
458             } catch (IOException JavaDoc e) {
459                 LOG.error(Messages.get().getBundle().key(
460                     Messages.LOG_CACHE_DTD_SYSTEM_ID_FAILURE_1,
461                     configuration.getDtdSystemLocation() + configuration.getDtdFilename()), e);
462             }
463         }
464     }
465
466     /**
467      * Loads the OpenCms configuration from the given XML URL.<p>
468      *
469      * @param url the base URL of the XML configuration to load
470      * @param configuration the configuration to load
471      * @throws SAXException in case of XML parse errors
472      * @throws IOException in case of file IO errors
473      */

474     private void loadXmlConfiguration(URL JavaDoc url, I_CmsXmlConfiguration configuration) throws SAXException JavaDoc, IOException JavaDoc {
475
476         // generate the file URL for the XML input
477
URL JavaDoc fileUrl = new URL JavaDoc(url, configuration.getXmlFileName());
478         if (LOG.isDebugEnabled()) {
479             LOG.debug(Messages.get().getBundle().key(Messages.LOG_LOAD_CONFIG_XMLFILE_1, fileUrl));
480         }
481
482         // create a backup of the configuration
483
backupXmlConfiguration(configuration);
484
485         // instantiate Digester and enable XML validation
486
m_digester = new Digester();
487         m_digester.setUseContextClassLoader(true);
488         m_digester.setValidating(true);
489         m_digester.setEntityResolver(new CmsXmlEntityResolver(null));
490         m_digester.setRuleNamespaceURI(null);
491         m_digester.setErrorHandler(new CmsXmlErrorHandler());
492
493         // add this class to the Digester
494
m_digester.push(configuration);
495
496         configuration.addXmlDigesterRules(m_digester);
497
498         // start the parsing process
499
m_digester.parse(fileUrl.openStream());
500     }
501
502     /**
503      * Removes all backups that are older then the given number of days.<p>
504      *
505      * @param daysToKeep the days to keep the backups for
506      */

507     private void removeOldBackups(long daysToKeep) {
508
509         long maxAge = (System.currentTimeMillis() - (daysToKeep * 24 * 60 * 60 * 1000));
510         File JavaDoc[] files = m_backupFolder.listFiles();
511         for (int i = 0; i < files.length; i++) {
512             File JavaDoc file = files[i];
513             long lastMod = file.lastModified();
514             if ((lastMod < maxAge) & (!file.getAbsolutePath().endsWith(CmsConfigurationManager.POSTFIX_ORI))) {
515                 file.delete();
516                 if (LOG.isDebugEnabled()) {
517                     LOG.debug(Messages.get().getBundle().key(Messages.LOG_REMOVE_CONFIG_FILE_1, file.getAbsolutePath()));
518                 }
519             }
520         }
521     }
522 }
Popular Tags