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.util.Collection;
24  import java.util.HashMap;
25  import java.util.Iterator;
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 org.apache.commons.xmlio.in.DefaultSimpleImportHandler;
32  import org.apache.commons.xmlio.in.SimpleImporter;
33  import org.apache.commons.xmlio.in.SimplePath;
34  import org.xml.sax.InputSource;
35  import org.xml.sax.helpers.AttributesImpl;
36  
37  /***
38   * @author Daniel Florey
39   *
40   */
41  public class XMLMessageProvider implements MessageProvider {
42      private static Logger logger = Logger.getLogger(XMLMessageProvider.class.getName());
43  
44      private static Map installedMessages = new HashMap();
45      private static Map messages = new HashMap();
46  
47      public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
48          Message message = findMessage(id, locale);
49          return message.getEntry(entry);
50      }
51  
52      public Map getEntries(String id, Locale locale) throws MessageNotFoundException {
53          Message message = findMessage(id, locale);
54          return message.getEntries();
55      }
56  
57      public static void install(String id, InputStream inputStream) {
58          logger.log(Level.FINE, "Installing messages '"+id+"'");
59          try {
60              Map applicationMessages = new HashMap();
61              SimpleImporter importer = new SimpleImporter();
62              importer.setIncludeLeadingCDataIntoStartElementCallback(true);
63              ConfigurationHandler handler = new ConfigurationHandler();
64              importer.addSimpleImportHandler(handler);
65              importer.parse(new InputSource(inputStream));
66              Map parsedMessages = handler.getMessages();
67              applicationMessages.putAll(parsedMessages);
68              messages.putAll(applicationMessages);
69              installedMessages.put(id, applicationMessages.keySet());
70          } catch (Exception exception) {
71              logger.log(Level.SEVERE, "Error while parsing messages", exception);
72          }
73      }
74      
75      public static void uninstall(String id) {
76          logger.log(Level.FINE, "Uninstalling messages '"+id+"'");
77          Collection messageKeys = (Collection)installedMessages.get(id);
78          for ( Iterator i = messageKeys.iterator(); i.hasNext(); ) {
79              String messageKey = (String)i.next();
80              messages.remove(messageKey);
81              logger.log(Level.FINE, "Removing message with key '"+messageKey+"'");
82          }
83          installedMessages.remove(id);
84      }
85      
86      public static void update(String id, InputStream inputStream) {
87          uninstall(id);
88          install(id, inputStream);
89      }
90          
91      private static Message findMessage(String id, Locale locale) {
92          Message message = lookupMessage(id, locale);
93          if (message == null) {
94              message = lookupMessage(id, Locale.getDefault());
95          }
96          if (message == null ) throw new MessageNotFoundException("Message with id "+id+" not found");
97          return message;
98      }
99  
100     private static Message lookupMessage(String id, Locale locale) {
101         StringBuffer keyBuffer = new StringBuffer(64);
102         keyBuffer.append(id);
103         if (locale.getLanguage() != null) keyBuffer.append("_" + locale.getLanguage());
104         if (locale.getCountry() != null) keyBuffer.append("_" + locale.getCountry());
105         if (locale.getVariant() != null) keyBuffer.append("_" + locale.getVariant());
106         String key = keyBuffer.toString();
107         if (messages.containsKey(key)) return (Message)messages.get(key);
108         while (key.lastIndexOf('_') > 0) {
109             key = key.substring(0, key.lastIndexOf('_'));
110             if (messages.containsKey(key)) return (Message)messages.get(key);
111         }
112         return null;
113     }
114 
115     static class ConfigurationHandler extends DefaultSimpleImportHandler {
116         private Map messages = new HashMap();
117         private String id;
118         private Message message;
119 
120         public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) {
121             if (path.matches("message")) {
122                 id = attributes.getValue("id");
123             } else if (path.matches("message/locale")) {
124                 message = new Message(id);
125                 message.setLanguage(attributes.getValue("language"));
126                 message.setCountry(attributes.getValue("country"));
127                 message.setVariant(attributes.getValue("variant"));
128             } else if (path.matches("message/locale/entry")) {
129                 String key = attributes.getValue("key");
130                 message.addEntry(key, leadingCDdata);
131             }
132         }
133 
134         public void endElement(SimplePath path, String name) {
135             if (path.matches("message/locale")) {
136                 messages.put(message.getKey(), message);
137             }
138         }
139         
140         Map getMessages() {
141             return messages;
142         }
143     }
144 
145     static class Message {
146         private String id, language, country, variant;
147         private Map entries = new HashMap();
148 
149         public Message(String id) {
150             this.id = id;
151         }
152 
153         public void addEntry(String key, String value) {
154             entries.put(key, value);
155         }
156 
157         public String getEntry(String key) {
158             return (String)entries.get(key);
159         }
160 
161         public Map getEntries() {
162             return entries;
163         }
164 
165         public void setLanguage(String language) {
166             this.language = language;
167         }
168 
169         public void setCountry(String country) {
170             this.country = country;
171         }
172 
173         public void setVariant(String variant) {
174             this.variant = variant;
175         }
176 
177         public String getKey() {
178             StringBuffer key = new StringBuffer(64);
179             key.append(id);
180             if (language != null) key.append("_" + language);
181             if (country != null) key.append("_" + country);
182             if (variant != null) key.append("_" + variant);
183             return key.toString();
184         }
185     }
186 }