View Javadoc

1   /*
2   *
3   * ====================================================================
4   *
5   * Licensed to the Apache Software Foundation (ASF) under one or more
6   * contributor license agreements.  See the NOTICE file distributed with
7   * this work for additional information regarding copyright ownership.
8   * The ASF licenses this file to You under the Apache License, Version 2.0
9   * (the "License"); you may not use this file except in compliance with
10  * the License.  You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21  package org.apache.commons.i18n;
22  
23  import java.io.InputStream;
24  import java.text.MessageFormat;
25  import java.util.HashMap;
26  import java.util.Locale;
27  import java.util.Map;
28  import java.util.logging.Level;
29  import java.util.logging.Logger;
30  
31  import javax.xml.parsers.SAXParser;
32  import javax.xml.parsers.SAXParserFactory;
33  
34  import org.xml.sax.Attributes;
35  import org.xml.sax.InputSource;
36  import org.xml.sax.helpers.DefaultHandler;
37  
38  /**
39   * The <code>XMLMessageProvider</code> provides messages defined in an XML format.
40   *  
41   */
42  public class XMLMessageProvider implements MessageProvider {
43      private static final Logger logger = Logger.getLogger(XMLMessageProvider.class.getName());
44  
45      private static SAXParserFactory factory = SAXParserFactory.newInstance();
46      
47      private Map messages = new HashMap();
48  
49      public XMLMessageProvider(InputStream inputStream) {
50          try {
51              Map applicationMessages = new HashMap();
52              SAXParser parser = factory.newSAXParser();
53              ConfigurationHandler handler = new ConfigurationHandler();
54              parser.parse(new InputSource(inputStream), handler);
55              Map parsedMessages = handler.getMessages();
56              applicationMessages.putAll(parsedMessages);
57              messages.putAll(applicationMessages);
58          } catch (Exception exception) {
59              String msg = I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_PARSING_ERROR);
60              logger.log(Level.SEVERE,msg,exception);
61              throw new RuntimeException(msg, exception);
62          }
63      }
64  
65      /* (non-Javadoc)
66       * @see org.apache.commons.i18n.MessageProvider#getText(java.lang.String, java.lang.String, java.util.Locale)
67       */
68      public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
69          Message message = findMessage(id, locale);
70          return message.getEntry(entry);
71      }
72  
73      /* (non-Javadoc)
74       * @see org.apache.commons.i18n.MessageProvider#getEntries(java.lang.String, java.util.Locale)
75       */
76      public Map getEntries(String id, Locale locale) throws MessageNotFoundException {
77          Message message = findMessage(id, locale);
78          return message.getEntries();
79      }
80  
81      private Message findMessage(String id, Locale locale) {
82          Message message = lookupMessage(id, locale);
83          if (message == null) {
84              message = lookupMessage(id, Locale.getDefault());
85          }
86          if (message == null ) throw new MessageNotFoundException(
87                  MessageFormat.format(
88                          I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.NO_MESSAGE_ENTRIES_FOUND),
89                          new String[] { id }));
90          return message;
91      }
92  
93      private Message lookupMessage(String id, Locale locale) {
94          String key = id + '_' + locale.toString();
95          if (messages.containsKey(key)) return (Message)messages.get(key);
96          locale = I18nUtils.getParentLocale(locale);
97          while (locale != null) {
98              key = id + '_' + locale.toString();
99              if (messages.containsKey(key)) return (Message)messages.get(key);
100             locale = I18nUtils.getParentLocale(locale);
101         }
102         return null;
103     }
104 
105     class ConfigurationHandler extends DefaultHandler {
106         private String id, key;
107         private Message message;
108         private StringBuffer cData;
109 
110         public void startElement(String namespaceUri, String localeName, String qName, Attributes attributes)  {
111             if (qName.matches("message")) {
112                 id = attributes.getValue("id");
113             } else if (qName.matches("locale")) {
114                 message = new Message(id);
115                 message.setLanguage(attributes.getValue("language"));
116                 message.setCountry(attributes.getValue("country"));
117                 message.setVariant(attributes.getValue("variant"));
118             } else if (qName.matches("entry")) {
119                 key = attributes.getValue("key");
120                 cData = new StringBuffer();
121             }
122         }
123         public void characters(char[] ch,
124                 int start,
125                 int length) {
126             if ( message != null && key != null && length > 0 ) {
127                 cData.append(ch, start, length);
128             }
129         }
130         
131         public void endElement(String namespaceUri, String localeName, String qName) {
132             if (qName.matches("locale")) {
133                 messages.put(message.getKey(), message);
134             } else if (qName.matches("entry")) {
135                 message.addEntry(key, cData.toString());
136                 key = null;
137             }
138         }
139         
140         Map getMessages() {
141             return messages;
142         }
143     }
144 
145     static class Message {
146         private final String id;
147         private String language, country, variant;
148         private Map entries = new HashMap();
149 
150         public Message(String id) {
151             this.id = id;
152         }
153 
154         public void addEntry(String key, String value) {
155             entries.put(key, value);
156         }
157 
158         public String getEntry(String key) {
159             return (String)entries.get(key);
160         }
161 
162         public Map getEntries() {
163             return entries;
164         }
165 
166         public void setLanguage(String language) {
167             this.language = language;
168         }
169 
170         public void setCountry(String country) {
171             this.country = country;
172         }
173 
174         public void setVariant(String variant) {
175             this.variant = variant;
176         }
177 
178         public String getKey() {
179             return id + '_' + new Locale((language != null) ? language : "",
180                     (country != null) ? country : "",
181                     (variant != null) ? variant : "").toString();
182         }
183     }
184 }