1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 }