KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > module > sitemesh > mapper > ConfigLoader


1 /*
2  * Title: ConfigLoader
3  * Description:
4  *
5  * This software is published under the terms of the OpenSymphony Software
6  * License version 1.1, of which a copy has been included with this
7  * distribution in the LICENSE.txt file.
8  */

9
10 package com.opensymphony.module.sitemesh.mapper;
11
12 import com.opensymphony.module.sitemesh.Config;
13 import com.opensymphony.module.sitemesh.Decorator;
14 import org.w3c.dom.*;
15 import org.xml.sax.SAXException JavaDoc;
16
17 import javax.servlet.ServletException JavaDoc;
18 import javax.xml.parsers.DocumentBuilder JavaDoc;
19 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
20 import javax.xml.parsers.ParserConfigurationException JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Map JavaDoc;
25
26 /**
27  * The ConfigLoader reads a configuration XML file that contains Decorator definitions
28  * (name, url, init-params) and path-mappings (pattern, name).
29  *
30  * <p>These can then be accessed by the getDecoratorByName() methods and getMappedName()
31  * methods respectively.</p>
32  *
33  * <p>The DTD for the configuration file in old (deprecated) format is located at
34  * <a HREF="http://www.opensymphony.com/dtds/sitemesh_1_0_decorators.dtd">
35  * http://www.opensymphony.com/dtds/sitemesh_1_0_decorators.dtd
36  * </a>.</p>
37  *
38  * <p>The DTD for the configuration file in new format is located at
39  * <a HREF="http://www.opensymphony.com/dtds/sitemesh_1_5_decorators.dtd">
40  * http://www.opensymphony.com/dtds/sitemesh_1_5_decorators.dtd
41  * </a>.</p>
42  *
43  * <p>Editing the config file will cause it to be auto-reloaded.</p>
44  *
45  * <p>This class is used by ConfigDecoratorMapper, and uses PathMapper for pattern matching.</p>
46  *
47  * @author <a HREF="mailto:joe@truemesh.com">Joe Walnes</a>
48  * @author <a HREF="mailto:pathos@pandora.be">Mathias Bogaert</a>
49  * @version $Revision: 1.6 $
50  *
51  * @see com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper
52  * @see com.opensymphony.module.sitemesh.mapper.PathMapper
53  */

54 public final class ConfigLoader {
55     private Map JavaDoc decorators = null;
56     private long configLastModified;
57
58     private File JavaDoc configFile = null;
59     private String JavaDoc configFileName = null;
60     private PathMapper pathMapper = null;
61
62     private Config config = null;
63
64     /** Create new ConfigLoader using supplied File. */
65     public ConfigLoader(File JavaDoc configFile) throws ServletException JavaDoc {
66         this.configFile = configFile;
67         this.configFileName = configFile.getName();
68         loadConfig();
69     }
70
71     /** Create new ConfigLoader using supplied filename and config. */
72     public ConfigLoader(String JavaDoc configFileName, Config config) throws ServletException JavaDoc {
73         this.config = config;
74         this.configFileName = configFileName;
75         if (config.getServletContext().getRealPath(configFileName) != null) {
76             this.configFile = new File JavaDoc(config.getServletContext().getRealPath(configFileName));
77         }
78         loadConfig();
79     }
80
81     /** Retrieve Decorator based on name specified in configuration file. */
82     public Decorator getDecoratorByName(String JavaDoc name) throws ServletException JavaDoc {
83         refresh();
84         return (Decorator)decorators.get(name);
85     }
86
87     /** Get name of Decorator mapped to given path. */
88     public String JavaDoc getMappedName(String JavaDoc path) throws ServletException JavaDoc {
89         refresh();
90         return pathMapper.get(path);
91     }
92
93     /** Load configuration from file. */
94     private synchronized void loadConfig() throws ServletException JavaDoc {
95         try {
96             // Build a document from the file
97
DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
98             DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
99
100             Document document = null;
101             if (configFile != null && configFile.canRead()) {
102                 // Keep time we read the file to check if the file was modified
103
configLastModified = configFile.lastModified();
104                 document = builder.parse(configFile);
105             }
106             else {
107                 document = builder.parse(config.getServletContext().getResourceAsStream(configFileName));
108             }
109
110             // Parse the configuration document
111
parseConfig(document);
112         }
113         catch (ParserConfigurationException JavaDoc e) {
114             throw new ServletException JavaDoc("Could not get XML parser", e);
115         }
116         catch (IOException JavaDoc e) {
117             throw new ServletException JavaDoc("Could not read the config file: " + configFileName, e);
118         }
119         catch (SAXException JavaDoc e) {
120             throw new ServletException JavaDoc("Could not parse the config file: " + configFileName, e);
121         }
122         catch (IllegalArgumentException JavaDoc e) {
123             throw new ServletException JavaDoc("Could not find the config file: " + configFileName, e);
124         }
125     }
126
127     /** Parse configuration from XML document. */
128     private synchronized void parseConfig(Document document) {
129         Element root = document.getDocumentElement();
130
131         // get the default directory for the decorators
132
String JavaDoc defaultDir = getAttribute(root, "defaultdir");
133         if (defaultDir == null) defaultDir = getAttribute(root, "defaultDir");
134
135         // Clear previous config
136
pathMapper = new PathMapper();
137         decorators = new HashMap JavaDoc();
138
139         // Get decorators
140
NodeList decoratorNodes = root.getElementsByTagName("decorator");
141         Element decoratorElement = null;
142
143         for (int i = 0; i < decoratorNodes.getLength(); i++) {
144             String JavaDoc name = null, page = null, uriPath = null, role = null;
145
146             // get the current decorator element
147
decoratorElement = (Element) decoratorNodes.item(i);
148
149             if (getAttribute(decoratorElement, "name") != null) {
150                 // The new format is used
151
name = getAttribute(decoratorElement, "name");
152                 page = getAttribute(decoratorElement, "page");
153                 uriPath = getAttribute(decoratorElement, "webapp");
154                 role = getAttribute(decoratorElement, "role");
155
156                 // Append the defaultDir
157
if (defaultDir != null && page != null && page.length() > 0 && !page.startsWith("/")) {
158                     if (page.charAt(0) == '/') page = defaultDir + page;
159                     else page = defaultDir + '/' + page;
160                 }
161
162                 // The uriPath must begin with a slash
163
if (uriPath != null && uriPath.length() > 0) {
164                     if (uriPath.charAt(0) != '/') uriPath = '/' + uriPath;
165                 }
166
167                 // Get all <pattern>...</pattern> and <url-pattern>...</url-pattern> nodes and add a mapping
168
populatePathMapper(decoratorElement.getElementsByTagName("pattern"), role, name);
169                populatePathMapper(decoratorElement.getElementsByTagName("url-pattern"), role, name);
170             }
171             else {
172                 // NOTE: Deprecated format
173
name = getContainedText(decoratorNodes.item(i), "decorator-name");
174                 page = getContainedText(decoratorNodes.item(i), "resource");
175                 // We have this here because the use of jsp-file is deprecated, but we still want
176
// it to work.
177
if (page == null) page = getContainedText(decoratorNodes.item(i), "jsp-file");
178             }
179
180             Map JavaDoc params = new HashMap JavaDoc();
181
182             NodeList paramNodes = decoratorElement.getElementsByTagName("init-param");
183             for (int ii = 0; ii < paramNodes.getLength(); ii++) {
184                 String JavaDoc paramName = getContainedText(paramNodes.item(ii), "param-name");
185                 String JavaDoc paramValue = getContainedText(paramNodes.item(ii), "param-value");
186                 params.put(paramName, paramValue);
187             }
188             storeDecorator(new DefaultDecorator(name, page, uriPath, role, params));
189         }
190
191         // Get (deprecated format) decorator-mappings
192
NodeList mappingNodes = root.getElementsByTagName("decorator-mapping");
193         for (int i = 0; i < mappingNodes.getLength(); i++) {
194             Element n = (Element)mappingNodes.item(i);
195             String JavaDoc name = getContainedText(mappingNodes.item(i), "decorator-name");
196
197             // Get all <url-pattern>...</url-pattern> nodes and add a mapping
198
populatePathMapper(n.getElementsByTagName("url-pattern"), null, name);
199         }
200     }
201
202    /**
203     * Extracts each URL pattern and adds it to the pathMapper map.
204     */

205    private void populatePathMapper(NodeList patternNodes, String JavaDoc role, String JavaDoc name) {
206       for (int j = 0; j < patternNodes.getLength(); j++) {
207           Element p = (Element)patternNodes.item(j);
208           Text patternText = (Text) p.getFirstChild();
209           if (patternText != null) {
210              String JavaDoc pattern = patternText.getData().trim();
211              if (pattern != null) {
212                  if (role != null) {
213                      // concatenate name and role to allow more
214
// than one decorator per role
215
pathMapper.put(name + role, pattern);
216                  }
217                  else {
218                      pathMapper.put(name, pattern);
219                  }
220              }
221          }
222       }
223    }
224
225    /** Override default behavior of element.getAttribute (returns the empty string) to return null. */
226     private static String JavaDoc getAttribute(Element element, String JavaDoc name) {
227         if (element != null && element.getAttribute(name) != null && element.getAttribute(name).trim() != "") {
228             return element.getAttribute(name).trim();
229         }
230         else {
231             return null;
232         }
233     }
234
235     /**
236      * With a given parent XML Element, find the text contents of the child element with
237      * supplied name.
238      */

239     private static String JavaDoc getContainedText(Node parent, String JavaDoc childTagName) {
240         try {
241             Node tag = ((Element)parent).getElementsByTagName(childTagName).item(0);
242             String JavaDoc text = ((Text)tag.getFirstChild()).getData();
243             return text;
244         }
245         catch (Exception JavaDoc e) {
246             return null;
247         }
248     }
249
250     /** Store Decorator in Map */
251     private void storeDecorator(Decorator d) {
252         if (d.getRole() != null) {
253             decorators.put(d.getName() + d.getRole(), d);
254         }
255         else {
256             decorators.put(d.getName(), d);
257         }
258     }
259
260     /** Check if configuration file has been updated, and if so, reload. */
261     private synchronized void refresh() throws ServletException JavaDoc {
262         if (configFile != null && configLastModified != configFile.lastModified()) loadConfig();
263     }
264 }
Popular Tags