1   package com.atlassian.core.util;
2   
3   import com.opensymphony.util.TextUtils;
4   import org.apache.log4j.Category;
5   import org.w3c.dom.Document;
6   import org.w3c.dom.Element;
7   import org.xml.sax.SAXException;
8   
9   import javax.xml.parsers.DocumentBuilder;
10  import javax.xml.parsers.DocumentBuilderFactory;
11  import javax.xml.parsers.ParserConfigurationException;
12  import java.io.IOException;
13  import java.net.URL;
14  import java.util.*;
15  
16  public class LocaleUtils
17  {
18      private static final Category log = Category.getInstance(LocaleUtils.class);
19  
20      public static final String LANGUAGE_DESCRIPTOR_FILENAME = "language-descriptor.xml";
21      public static final String LOCALE_TAG_NAME = "locale";
22  
23      public List installedLocales;
24  
25  
26      /**
27       * This method locates all installed language bundles that are found on the classpath by looking for
28       * {@link #LANGUAGE_DESCRIPTOR_FILENAME} files on the classpath, and parsing the value of the
29       * {@link #LOCALE_TAG_NAME} element.
30       * 
31       * @throws IOException when problems arise retrieving resources from the classpath
32       */
33      public List getInstalledLocales() throws IOException
34      {
35          if (installedLocales == null)
36          {
37              installedLocales = new ArrayList();
38              URL url = null;
39              final Enumeration localeDescriptors = ClassLoaderUtils.getResources(LANGUAGE_DESCRIPTOR_FILENAME, this.getClass());
40              while (localeDescriptors.hasMoreElements())
41              {
42                  try
43                  {
44                      url = (URL) localeDescriptors.nextElement();
45                      DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
46                      Document xmlDoc = db.parse(url.openConnection().getInputStream());
47                      Element root = xmlDoc.getDocumentElement();
48                      String locale = XMLUtils.getContainedText(root, LOCALE_TAG_NAME);
49                      if (TextUtils.stringSet(locale))
50                      {
51                          installedLocales.add(getLocale(locale));
52                      }
53                      else
54                      {
55                          throw new IllegalArgumentException("The " + LOCALE_TAG_NAME + " element must be set in " + url);
56                      }
57                  }
58                  catch (IOException e)
59                  {
60                      log.error("Error while reading language descriptor '" + url + "'.", e);
61                  }
62                  catch (ParserConfigurationException e)
63                  {
64                      log.error("Error while parsing language descriptor '" + url + "'.", e);
65                  }
66                  catch (SAXException e)
67                  {
68                      log.error("Error while parsing language descriptor '" + url + "'.", e);
69                  }
70              }
71              // Sort the locales by their display names
72              Collections.sort(installedLocales, new LocaleComparator());
73          }
74  
75          return installedLocales;
76      }
77  
78      /**
79       * Creates a locale from the given string.
80       * 
81       * @param locale 
82       * @return 
83       */
84      public Locale getLocale(String locale)
85      {
86          if (TextUtils.stringSet(locale))
87          {
88              int _pos = locale.indexOf("_");
89              if (_pos != -1)
90              {
91                  return new Locale(locale.substring(0, _pos), locale.substring(_pos + 1));
92              }
93              else
94              {
95                  return new Locale(locale, "");
96              }
97          }
98          return null;
99      }
100 }