/**
* Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.common.localization;
import org.apache.log4j.Logger;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
/**
* Class that extends the java.util.ResourceBundle class that stores
* the strings in an XML format similar to a property file.
* The format is as follows:
*
* <messages>
* <msg id="getMessage">Get this</msg>
* <msg id="oneArg">one arg: {0}</msg>
* <msg id="twoArg">two arg: {0} {1}</msg>
* <msg id="threeArg">three arg: {0} {1} {2}</msg>
* </messages>
*
* Where the bundle gets built with the keys being the "id" attribute
* of the XML tag and the values being contained within the value of the
* <msg> tag itself. Message substitution is supported.
*
* @version $Rev$
*/
public final class XmlResourceBundle extends java.util.ResourceBundle {
private static Logger log = Logger.getLogger(XmlResourceBundle.class);
/**
* Map of key/value pairs
*/
private Map<String, String> strings;
/** Constructor
*/
public XmlResourceBundle() {
// empty
}
/**
* Creates a property resource bundle.
* @param filelocation location of XML file to parse
* @throws IOException if the file can't be parsed/loaded
*/
public XmlResourceBundle(String filelocation) throws IOException {
strings = new HashMap<String, String>();
try {
// These are namespace URLs, and don't actually
// resolve to real documents that get downloaded on the
// web.
// Turn on validation
String validationFeature
= "http://xml.org/sax/features/validation";
// Turn on schema validation
String schemaFeature
= "http://apache.org/xml/features/validation/schema";
// We have to store the xsd locally because we may not have
// access to it over the web when starting up the service.
String xsdLocation =
this.getClass().getResource("/xliff-core-1.1.xsd").toString();
XMLReader parser = XMLReaderFactory.
createXMLReader("org.apache.xerces.parsers.SAXParser");
parser.setFeature(validationFeature, false);
parser.setFeature(schemaFeature, false);
parser.setProperty("http://apache.org/xml/properties/schema/" +
"external-noNamespaceSchemaLocation", xsdLocation);
XmlResourceBundleParser handler = new XmlResourceBundleParser();
parser.setContentHandler(handler);
parser.parse(new InputSource(this.getClass().
getResourceAsStream(filelocation)));
strings = handler.getMessages();
}
catch (SAXException e) {
// This really should never happen, because without this file,
// the whole UI stops working.
log.error("Could not setup parser");
throw new IOException("Could not load XML bundle: " + filelocation);
}
// TODO: put the xml strings in the Map
}
/**
* Overrides the java.util.ResourceBundle.handleGetObject.
* @param key the key to lookup out of the bundle
* @return The value found. This will be a java.lang.String and can be cased
* accordingly.
*/
public Object handleGetObject(String key) {
return strings.get(key);
}
/**
* ResourceBundle.getKeys() implemenatation
* @return Enumeration of the keys contained in this bundle.
* Useful for searching for a partial match.
*/
public Enumeration<String> getKeys() {
List<String> keys = new LinkedList<String>();
if (parent != null) {
Enumeration<String> e = parent.getKeys();
while (e.hasMoreElements()) {
keys.add(e.nextElement());
}
}
Iterator<String> itr = strings.keySet().iterator();
while (itr.hasNext()) {
keys.add(itr.next());
}
// Ugh, have to convert back to the old Enumeration interface
// This isn't pretty but it works.
return new Vector<String>(keys).elements();
}
}