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