View Javadoc

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