KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > XMLResources


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util;
19
20 import org.apache.oro.text.perl.MalformedPerl5PatternException;
21 import org.apache.oro.text.perl.Perl5Util;
22 import org.w3c.dom.*;
23
24 import javax.xml.parsers.DocumentBuilder JavaDoc;
25 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
26 import java.io.File JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Map JavaDoc;
30
31 /*
32  * This is derived from the SQLResources.java class that we have been
33  * using to provide SQL strings based upon the particular drive being
34  * used.
35  *
36  * The format is indentical to the format used by SQLResources. The
37  * only difference are the names of the elements and attributes. A
38  * mapping is as follows:
39  *
40  * sqlResources xmlResources
41  * ------------ ------------
42  * sqlResources resources
43  * dbMatchers matchers
44  * dbMatcher matcher
45  * db for
46  * databaseProductName match
47  * sqlDefs group
48  * sql resource
49  *
50  * This class provides String resources defined in XML. Resources are
51  * organized into groups, and identified by name. For each resource
52  * there can be a standard value, and custom values matched by regular
53  * expression.
54  *
55  * The structure of the XML file is:
56  *
57  * <resources>
58  * <matchers>
59  * &lt;matcher for="<i>label</i>" match="<i>regular expression</i>"/&gt;
60  * ...
61  * &lt;/matchers&gt;
62  * &lt;group name="<i>group name</i>"&gt;
63  * &lt;resource name="<i>resouce name</i>" [for="<i>match label</i>"]&gt;<i>text, including ${placeholders}, which will be replaced at runtime.</i>&lt;/resource&gt;
64  * ...
65  * &lt;/group&gt;
66  * <i>... more &lt;group&gt; elements ...</i>
67  * &lt;/resources&gt;
68  *
69  */

70 public class XMLResources
71 {
72     /**
73      * A map of statement types to resource strings
74      */

75     private Map JavaDoc m_resource = new HashMap JavaDoc();
76
77     /**
78      * A set of all used String values
79      */

80     static private Map JavaDoc stringTable = java.util.Collections.synchronizedMap(new HashMap JavaDoc());
81
82     /**
83      * A Perl5 regexp matching helper class
84      */

85     private Perl5Util m_perl5Util = new Perl5Util();
86
87     /**
88      * Configures an XMLResources object to provide string statements from a file.
89      *
90      * Parameters encoded as $(parameter} in the input file are
91      * replace by values from the parameters Map, if the named parameter exists.
92      * Parameter values may also be specified in the resourceSection element.
93      *
94      * @param xmlFile the input file containing the string definitions
95      * @param group xml element containing the strings to be used
96      * @param select if customized elements exist for this value, use them instead of the default
97      * @param configParameters a map of parameters (name-value string pairs) which are
98      * replaced where found in the input strings
99      */

100     public void init(File JavaDoc xmlFile, String JavaDoc group,
101                      String JavaDoc select, Map JavaDoc configParameters)
102         throws Exception JavaDoc
103     {
104         // Parse the xmlFile as an XML document.
105
DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
106         DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
107         Document doc = builder.parse(xmlFile);
108
109         // First process the matchers, to select the statements to use.
110
Element matcherElement =
111             (Element)(doc.getElementsByTagName("matchers").item(0));
112         String JavaDoc selectTag = null;
113         if ( matcherElement != null ) {
114             selectTag = match(select, matcherElement);
115             m_perl5Util = null; // release the PERL matcher!
116
}
117
118         // Now get the section defining strings for the group required.
119
NodeList sections = doc.getElementsByTagName("group");
120         int sectionsCount = sections.getLength();
121         Element sectionElement = null;
122         for (int i = 0; i < sectionsCount; i++ ) {
123             sectionElement = (Element)(sections.item(i));
124             String JavaDoc sectionName = sectionElement.getAttribute("name");
125             if ( sectionName != null && sectionName.equals(group) ) {
126                 break;
127             }
128
129         }
130         if ( sectionElement == null ) {
131             StringBuffer JavaDoc exceptionBuffer =
132                 new StringBuffer JavaDoc(64)
133                         .append("Error loading string definition file. ")
134                         .append("The element named \'")
135                         .append(group)
136                         .append("\' does not exist.");
137             throw new RuntimeException JavaDoc(exceptionBuffer.toString());
138         }
139
140         // Get parameters defined within the file as defaults,
141
// and use supplied parameters as overrides.
142
Map JavaDoc parameters = new HashMap JavaDoc();
143         // First read from the <params> element, if it exists.
144
Element parametersElement =
145             (Element)(sectionElement.getElementsByTagName("parameters").item(0));
146         if ( parametersElement != null ) {
147             NamedNodeMap params = parametersElement.getAttributes();
148             int paramCount = params.getLength();
149             for (int i = 0; i < paramCount; i++ ) {
150                 Attr param = (Attr)params.item(i);
151                 String JavaDoc paramName = param.getName();
152                 String JavaDoc paramValue = param.getValue();
153                 parameters.put(paramName, paramValue);
154             }
155         }
156         // Then copy in the parameters supplied with the call.
157
parameters.putAll(configParameters);
158
159         // 2 maps - one for storing default statements,
160
// the other for statements with a "for" attribute matching this
161
// connection.
162
Map JavaDoc defaultStrings = new HashMap JavaDoc();
163         Map JavaDoc selectTagStrings = new HashMap JavaDoc();
164
165         // Process each string resource, replacing string parameters,
166
// and adding to the appropriate map..
167
NodeList resDefs = sectionElement.getElementsByTagName("resource");
168         int resCount = resDefs.getLength();
169         for ( int i = 0; i < resCount; i++ ) {
170             // See if this needs to be processed (is default or product specific)
171
Element resElement = (Element)(resDefs.item(i));
172             String JavaDoc resSelect = resElement.getAttribute("for");
173             Map JavaDoc resMap;
174             if ( resSelect.equals("")) {
175                 // default
176
resMap = defaultStrings;
177             }
178             else if (resSelect.equals(selectTag) ) {
179                 // Specific to this product
180
resMap = selectTagStrings;
181             }
182             else {
183                 // for a different product
184
continue;
185             }
186
187             // Get the key and value for this string resource.
188
String JavaDoc resKey = resElement.getAttribute("name");
189             if ( resKey == null ) {
190                 // ignore elements without a "name" attribute.
191
continue;
192             }
193             String JavaDoc resString = resElement.getFirstChild().getNodeValue();
194
195             // Do parameter replacements for this string resource.
196
Iterator JavaDoc paramNames = parameters.keySet().iterator();
197             while ( paramNames.hasNext() ) {
198                 String JavaDoc paramName = (String JavaDoc)paramNames.next();
199                 String JavaDoc paramValue = (String JavaDoc)parameters.get(paramName);
200
201                 StringBuffer JavaDoc replaceBuffer =
202                     new StringBuffer JavaDoc(64)
203                             .append("${")
204                             .append(paramName)
205                             .append("}");
206                 resString = substituteSubString(resString, replaceBuffer.toString(), paramValue);
207             }
208
209             // See if we already have registered a string of this value
210
String JavaDoc shared = (String JavaDoc) stringTable.get(resString);
211             // If not, register it -- we will use it next time
212
if (shared == null) {
213                 stringTable.put(resString, resString);
214             } else {
215                 resString = shared;
216             }
217
218             // Add to the resMap - either the "default" or the "product" map
219
resMap.put(resKey, resString);
220         }
221
222         // Copy in default strings, then overwrite product-specific ones.
223
m_resource.putAll(defaultStrings);
224         m_resource.putAll(selectTagStrings);
225     }
226
227     /**
228      * Compares the "select" value against a set of regular expressions
229      * defined in XML. The first successful match defines the name of a
230      * selector tag. This value is then used to choose the specific
231      * expressions to use.
232      *
233      * @param select the String to be checked
234      * @param matchersElement the XML element containing selector patterns
235      *
236      * @return the selector tag that will be used to select custom resources
237      *
238      */

239     private String JavaDoc match(String JavaDoc select, Element matchersElement)
240         throws MalformedPerl5PatternException
241     {
242         String JavaDoc selectTagName = select;
243     
244         NodeList matchers = matchersElement.getElementsByTagName("matcher");
245         for ( int i = 0; i < matchers.getLength(); i++ ) {
246             // Get the values for this matcher element.
247
Element matcher = (Element)matchers.item(i);
248             String JavaDoc matchName = matcher.getAttribute("for");
249             StringBuffer JavaDoc selectTagPatternBuffer =
250                 new StringBuffer JavaDoc(64)
251                         .append("/")
252                         .append(matcher.getAttribute("match"))
253                         .append("/i");
254
255             // If the select string matches the pattern, use the match
256
// name from this matcher.
257
if ( m_perl5Util.match(selectTagPatternBuffer.toString(), selectTagName) ) {
258                 return matchName;
259             }
260         }
261         return null;
262     }
263
264     /**
265      * Replace substrings of one string with another string and return altered string.
266      * @param input input string
267      * @param find the string to replace
268      * @param replace the string to replace with
269      * @return the substituted string
270      */

271     static private String JavaDoc substituteSubString( String JavaDoc input,
272                                                String JavaDoc find,
273                                                String JavaDoc replace )
274     {
275         int find_length = find.length();
276         int replace_length = replace.length();
277
278         StringBuffer JavaDoc output = new StringBuffer JavaDoc(input);
279         int index = input.indexOf(find);
280         int outputOffset = 0;
281
282         while ( index > -1 ) {
283             output.replace(index + outputOffset, index + outputOffset + find_length, replace);
284             outputOffset = outputOffset + (replace_length - find_length);
285
286             index = input.indexOf(find, index + find_length);
287         }
288
289         String JavaDoc result = output.toString();
290         return result;
291     }
292
293     /**
294      * Returns a named string for the specified connection, replacing
295      * parameters with the values set.
296      *
297      * @param name the name of the String resource required.
298      * @return the requested resource
299      */

300     public String JavaDoc getString(String JavaDoc name)
301     {
302         return (String JavaDoc)m_resource.get(name);
303     }
304
305     /**
306      * Returns a named string for the specified connection, replacing
307      * parameters with the values set.
308      *
309      * @param name the name of the String resource required.
310      * @param required true if the resource is required
311      * @return the requested resource
312      * @throws ConfigurationException
313      * if a required resource cannot be found.
314      */

315     public String JavaDoc getString(String JavaDoc name, boolean required)
316     {
317         String JavaDoc str = getString(name);
318
319         if (str == null && required) {
320             StringBuffer JavaDoc exceptionBuffer =
321                 new StringBuffer JavaDoc(64)
322                         .append("Required String resource: '")
323                         .append(name)
324                         .append("' was not found.");
325             throw new RuntimeException JavaDoc(exceptionBuffer.toString());
326         }
327         return str;
328     }
329
330     /**
331      * Returns a named string, replacing parameters with the values set.
332      *
333      * @param name the name of the String resource required.
334      * @param parameters a map of parameters (name-value string pairs) which are
335      * replaced where found in the input strings
336      * @return the requested resource
337      */

338     public String JavaDoc getString(String JavaDoc name, Map JavaDoc parameters)
339     {
340         return replaceParameters(getString(name), parameters);
341     }
342
343     /**
344      * Returns a named string, replacing parameters with the values set.
345      *
346      * @param name the name of the String resource required.
347      * @param parameters a map of parameters (name-value string pairs) which are
348      * replaced where found in the input strings
349      * @return the requested resource
350      */

351     static public String JavaDoc replaceParameters(String JavaDoc str, Map JavaDoc parameters)
352     {
353         // Do parameter replacements for this string resource.
354
Iterator JavaDoc paramNames = parameters.keySet().iterator();
355         while ( paramNames.hasNext() ) {
356             String JavaDoc paramName = (String JavaDoc)paramNames.next();
357             String JavaDoc paramValue = (String JavaDoc)parameters.get(paramName);
358
359             StringBuffer JavaDoc replaceBuffer = new StringBuffer JavaDoc(64).append("${").append(paramName).append("}");
360             str = substituteSubString(str, replaceBuffer.toString(), paramValue);
361         }
362
363         return str;
364     }
365 }
366
Popular Tags