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.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 }