Clean up before implementing i18n support
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 14 Oct 2015 11:06:16 +0000 (11:06 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 14 Oct 2015 11:06:16 +0000 (11:06 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8482 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

14 files changed:
org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java
org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/i18n/Msg.java
org.argeo.cms/src/org/argeo/cms/internal/auth/ConsoleCallbackHandler.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelHeader.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/widgets/auth/CmsLogin.java
org.argeo.cms/src/org/argeo/cms/widgets/auth/CompositeCallbackHandler.java
org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java
org.argeo.util/src/org/argeo/util/LocaleCallback.java [deleted file]
org.argeo.util/src/org/argeo/util/LocaleChoice.java [new file with mode: 0644]

index 932b847e3849aa35f08a6f28dcbf4664910094d7..26b96d43c842a66bf63d94ffa3d433a6d50a3e2b 100644 (file)
@@ -8,10 +8,6 @@ public interface AuthConstants {
        final static String LOGIN_CONTEXT_SYSTEM = "SYSTEM";
        final static String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER";
 
-       // HTTP
-       @Deprecated
-       final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext";
-
        // RESERVED ROLES
        public final static String ROLE_KERNEL = "OU=node";
        public final static String ROLES_BASEDN = "ou=roles,ou=node";
@@ -23,8 +19,4 @@ public interface AuthConstants {
        // user U anonymous = everyone
        public final static String ROLE_USER = "cn=user," + ROLES_BASEDN;
        public final static String ROLE_ANONYMOUS = "cn=anonymous," + ROLES_BASEDN;
-
-       // SHARED STATE KEYS
-       //public final static String BUNDLE_CONTEXT_KEY = "org.argeo.security.bundleContext";
-       //public final static String AUTHORIZATION_KEY = "org.argeo.security.authorization";
 }
index ea8821185d78d4badf8c4ea20d1c13a98f04e76d..53e48e8c1ea4089eb13e7d5bd336c98619dc60c9 100644 (file)
@@ -2,12 +2,14 @@ package org.argeo.cms.auth;
 
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.LanguageCallback;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
@@ -19,6 +21,7 @@ import javax.servlet.http.HttpSession;
 
 import org.argeo.ArgeoException;
 import org.argeo.cms.internal.kernel.Activator;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.useradmin.Authorization;
@@ -60,9 +63,10 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants {
                        NameCallback nameCallback = new NameCallback("User");
                        PasswordCallback passwordCallback = new PasswordCallback(
                                        "Password", false);
+                       LanguageCallback langCallback = new LanguageCallback();
                        try {
                                callbackHandler.handle(new Callback[] { httpCallback,
-                                               nameCallback, passwordCallback });
+                                               nameCallback, passwordCallback, langCallback });
                        } catch (IOException e) {
                                throw new LoginException("Cannot handle http callback: "
                                                + e.getMessage());
@@ -77,20 +81,12 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants {
                                        authorization = (Authorization) request.getSession()
                                                        .getAttribute(HttpContext.AUTHORIZATION);
                        }
-                       // if (authorization == null || authorization.getName() == null)
-                       // if (!isAnonymous) {
-                       // // ask for username and password
-                       // NameCallback nameCallback = new NameCallback("User");
-                       // PasswordCallback passwordCallback = new PasswordCallback(
-                       // "Password", false);
-                       //
-                       // // handle callbacks
-                       // try {
-                       // callbackHandler.handle(new Callback[] { nameCallback,
-                       // passwordCallback });
-                       // } catch (Exception e) {
-                       // throw new ArgeoException("Cannot handle callbacks", e);
-                       // }
+
+                       // i18n
+                       Locale locale = langCallback.getLocale();
+                       if (locale == null)
+                               locale = Locale.getDefault();
+                       UiContext.setLocale(locale);
 
                        if (authorization == null) {
                                // create credentials
index b87b7b3d5624b61fe7dc6591bb14f6b66eacf6f4..64982f6c7ce0131fad298f14afa20a2c0cb7448a 100644 (file)
@@ -6,7 +6,7 @@ import java.util.Locale;
 import java.util.ResourceBundle;
 
 import org.argeo.cms.CmsException;
-import org.eclipse.rap.rwt.RWT;
+import org.argeo.eclipse.ui.specific.UiContext;
 
 /** A single message to be internationalised. */
 public class Msg {
@@ -49,7 +49,7 @@ public class Msg {
        /** When used as the first word of a sentence. */
        public String lead() {
                String raw = toString();
-               return raw.substring(0, 1).toUpperCase(RWT.getLocale())
+               return raw.substring(0, 1).toUpperCase(UiContext.getLocale())
                                + raw.substring(1);
        }
 
@@ -67,7 +67,7 @@ public class Msg {
                int lastDot = key.lastIndexOf('.');
                String className = key.substring(0, lastDot);
                String fieldName = key.substring(lastDot + 1);
-               Locale locale = RWT.getLocale();
+               Locale locale = UiContext.getLocale();
                ResourceBundle rb = ResourceBundle.getBundle(className, locale,
                                msg.getClassLoader());
                return rb.getString(fieldName);
index 7ea9c07379b8d8b45c4e30f5595dbf90769d967f..d5c6f002473a622da76d295b4194c6bb304d863e 100644 (file)
@@ -14,7 +14,7 @@ import javax.security.auth.callback.TextOutputCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
 import org.argeo.ArgeoException;
-import org.argeo.util.LocaleCallback;
+import org.argeo.util.LocaleChoice;
 
 /** Callback handler to be used with a command line UI. */
 public class ConsoleCallbackHandler implements CallbackHandler {
@@ -49,9 +49,9 @@ public class ConsoleCallbackHandler implements CallbackHandler {
                                char[] answer = console.readPassword();
                                callback.setPassword(answer);
                                Arrays.fill(answer, ' ');
-                       } else if (callbacks[i] instanceof LocaleCallback) {
-                               LocaleCallback callback = (LocaleCallback) callbacks[i];
-                               writer.write(callback.getPrompt());
+                       } else if (callbacks[i] instanceof LocaleChoice) {
+                               LocaleChoice callback = (LocaleChoice) callbacks[i];
+                               writer.write("Language");
                                writer.write("\n");
                                for (int j = 0; j < callback.getAvailableLocales().size(); j++) {
                                        Locale locale = callback.getAvailableLocales().get(j);
index a942b4b18452816aa11fcb218f27affda90a10d5..1d40c99463c07e58a35ae59b1b900040acc5f7fb 100644 (file)
@@ -22,7 +22,7 @@ public class Activator implements BundleActivator {
        }
 
        private static BundleContext bundleContext;
-       private Kernel kernel;
+       private static Kernel kernel;
 
        @Override
        public void start(BundleContext context) throws Exception {
@@ -54,6 +54,10 @@ public class Activator implements BundleActivator {
                return bundleContext;
        }
 
+       public static KernelHeader getKernelHeader() {
+               return kernel;
+       }
+
        /**
         * @return a String which is guaranteed to be unique between and constant
         *         within a Java static context (typically a VM launch)
index 68b3fa2891bf784ab5be47a33c254e1fa67fdc33..b95c195584d3986734efcef3b81f8fca50453819 100644 (file)
@@ -54,7 +54,7 @@ import bitronix.tm.TransactionManagerServices;
  * <li>OS access</li>
  * </ul>
  */
-final class Kernel implements KernelConstants, ServiceListener {
+final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
        /*
         * REGISTERED SERVICES
         */
@@ -100,12 +100,13 @@ final class Kernel implements KernelConstants, ServiceListener {
        }
 
        private void doInit() {
+               long begin = System.currentTimeMillis();
+
+               // Use CMS bundle classloader
                ClassLoader currentContextCl = Thread.currentThread()
                                .getContextClassLoader();
                Thread.currentThread().setContextClassLoader(
                                Kernel.class.getClassLoader());
-               long begin = System.currentTimeMillis();
-
                // KernelUtils.logFrameworkProperties(log);
 
                try {
index f528f6f7007dab15568f6d433f3d343a70fa027e..9f45edb7fc662cd07859e0f68d771f9310674f1c 100644 (file)
@@ -18,6 +18,8 @@ public interface KernelConstants {
 
        final static String TRANSACTIONS_HOME = "argeo.node.transactions.home";
 
+       final static String I18N_AVAILABLE_LOCALES = "argeo.i18n.availableLocales";
+
        // Node Security
        final static String ROLES_URI = "argeo.node.roles.uri";
        /** URI to an LDIF file or LDAP server used as initialization or backend */
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelHeader.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelHeader.java
new file mode 100644 (file)
index 0000000..f4d4d84
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.cms.internal.kernel;
+
+public interface KernelHeader {
+
+}
index 3f784407a3f99598152c4241c10a359bec650994..04e4f3c9f551e67fd8094066a6c95ab39ba9b4b2 100644 (file)
@@ -8,6 +8,7 @@ import java.io.IOException;
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.LanguageCallback;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
@@ -21,6 +22,7 @@ import org.argeo.cms.CmsView;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallback;
 import org.argeo.cms.util.CmsUtils;
+import org.argeo.util.LocaleChoice;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseAdapter;
@@ -38,6 +40,7 @@ import org.eclipse.swt.widgets.Text;
 public class CmsLogin implements CmsStyles, CallbackHandler {
        private Text username, password;
        private Composite credentialsBlock;
+       private LocaleChoice localeChoice = null;
 
        private final CmsView cmsView;
 
@@ -177,6 +180,10 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                                                .getTextChars());
                        else if (callback instanceof HttpRequestCallback)
                                ((HttpRequestCallback) callback).setRequest(RWT.getRequest());
+                       else if (callback instanceof LanguageCallback
+                                       && localeChoice != null)
+                               ((LanguageCallback) callback).setLocale(localeChoice
+                                               .getSelectedLocale());
                }
        }
 
index a87a1458cd4881d0f9478f76db932e714b40b091..bc99bc48bb8ff362d9e80e2becaac1f2e5dceaa3 100644 (file)
@@ -10,7 +10,7 @@ import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.TextOutputCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
-import org.argeo.util.LocaleCallback;
+import org.argeo.util.LocaleChoice;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.KeyListener;
@@ -40,7 +40,7 @@ import org.eclipse.swt.widgets.Text;
  * <p>
  * Supported Argeo {@link Callback}s are:<br>
  * <ul>
- * <li>{@link LocaleCallback}</li>
+ * <li>{@link LocaleChoice}</li>
  * </ul>
  * </p>
  */
@@ -98,7 +98,7 @@ public class CompositeCallbackHandler extends Composite implements
                if (callback instanceof TextOutputCallback
                                || callback instanceof NameCallback
                                || callback instanceof PasswordCallback
-                               || callback instanceof LocaleCallback) {
+                               || callback instanceof LocaleChoice) {
                        return;
                } else {
                        throw new UnsupportedCallbackException(callback);
@@ -137,8 +137,8 @@ public class CompositeCallbackHandler extends Composite implements
                                createNameHandler(composite, (NameCallback) callback);
                        } else if (callback instanceof PasswordCallback) {
                                createPasswordHandler(composite, (PasswordCallback) callback);
-                       } else if (callback instanceof LocaleCallback) {
-                               createLocaleHandler(composite, (LocaleCallback) callback);
+                       } else if (callback instanceof LocaleChoice) {
+                               createLocaleHandler(composite, (LocaleChoice) callback);
                        }
                }
        }
@@ -220,12 +220,12 @@ public class CompositeCallbackHandler extends Composite implements
        }
 
        protected Combo createLocaleHandler(Composite composite,
-                       final LocaleCallback callback) {
+                       final LocaleChoice callback) {
                String[] labels = callback.getSupportedLocalesLabels();
                if (labels.length == 0)
                        return null;
                Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
+               label.setText("Language");
 
                final Combo combo = new Combo(composite, SWT.READ_ONLY);
                combo.setItems(labels);
index ce50873f8b185589684492670c8cc97a6f944e6e..82b60612404b565875b3faeb51e0dc77bf810b2b 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.eclipse.ui.specific;
 
+import java.util.Locale;
+
 import javax.servlet.http.HttpServletRequest;
 
 import org.eclipse.rap.rwt.RWT;
@@ -12,6 +14,14 @@ public class UiContext {
                return RWT.getRequest();
        }
 
+       public static Locale getLocale() {
+               return RWT.getUISession().getLocale();
+       }
+
+       public static void setLocale(Locale locale) {
+               RWT.getUISession().setLocale(locale);
+       }
+
        /** Can always be null */
        @SuppressWarnings("unchecked")
        public static <T> T getData(String key) {
index 6a582f83f75e948dc60b8fb9680e3aa9b49033a4..c176ba62b59fc4d4e13372cfc50e870a140b2046 100644 (file)
@@ -15,8 +15,6 @@
  */
 package org.argeo.security.ui.rap;
 
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
-
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -49,6 +47,7 @@ import org.eclipse.ui.PlatformUI;
  * subject.
  */
 public class SecureEntryPoint implements EntryPoint {
+       final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext";
        private final static Log log = LogFactory.getLog(SecureEntryPoint.class);
 
        /**
@@ -77,7 +76,7 @@ public class SecureEntryPoint implements EntryPoint {
                HttpServletRequest httpRequest = RWT.getRequest();
                final HttpSession httpSession = httpRequest.getSession();
                AccessControlContext acc = (AccessControlContext) httpSession
-                               .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
+                               .getAttribute(ACCESS_CONTROL_CONTEXT);
 
                final Subject subject;
                if (acc != null
diff --git a/org.argeo.util/src/org/argeo/util/LocaleCallback.java b/org.argeo.util/src/org/argeo/util/LocaleCallback.java
deleted file mode 100644 (file)
index ac47e54..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.util;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.LanguageCallback;
-
-/** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */
-public class LocaleCallback implements Callback {
-       private List<Locale> availableLocales = new ArrayList<Locale>();
-
-       private Integer selectedIndex = null;
-       private Integer defaultIndex = null;
-       private String prompt = "Language";
-
-       public LocaleCallback(Integer defaultIndex, List<Locale> availableLocales) {
-               this.availableLocales = Collections
-                               .unmodifiableList(new ArrayList<Locale>(availableLocales));
-               this.defaultIndex = defaultIndex;
-               this.selectedIndex = defaultIndex;
-       }
-
-       /**
-        * Convenience constructor based on a comma separated list of iso codes (en,
-        * en_US, fr_CA, etc.). Default selection is default locale.
-        */
-       public LocaleCallback(String locales) {
-               if (locales == null || locales.trim().equals(""))
-                       return;
-               String[] codes = locales.split(",");
-               for (int i = 0; i < codes.length; i++) {
-                       String code = codes[i];
-                       // variant not supported
-                       int indexUnd = code.indexOf("_");
-                       Locale locale;
-                       if (indexUnd > 0) {
-                               String language = code.substring(0, indexUnd);
-                               String country = code.substring(indexUnd + 1);
-                               locale = new Locale(language, country);
-                       } else {
-                               locale = new Locale(code);
-                       }
-                       availableLocales.add(locale);
-                       if (locale.equals(Locale.getDefault()))
-                               defaultIndex = i;
-               }
-
-               if (defaultIndex == null)
-                       defaultIndex = 0;
-
-               this.selectedIndex = defaultIndex;
-       }
-
-       public String[] getSupportedLocalesLabels() {
-               String[] labels = new String[availableLocales.size()];
-               for (int i = 0; i < availableLocales.size(); i++) {
-                       Locale locale = availableLocales.get(i);
-                       if (locale.getCountry().equals(""))
-                               labels[i] = locale.getDisplayLanguage(locale) + " ["
-                                               + locale.getLanguage() + "]";
-                       else
-                               labels[i] = locale.getDisplayLanguage(locale) + " ("
-                                               + locale.getDisplayCountry(locale) + ") ["
-                                               + locale.getLanguage() + "_" + locale.getCountry()
-                                               + "]";
-
-               }
-               return labels;
-       }
-
-       public Locale getSelectedLocale() {
-               if (selectedIndex == null)
-                       return null;
-               return availableLocales.get(selectedIndex);
-       }
-
-       public void setSelectedIndex(Integer selectedIndex) {
-               this.selectedIndex = selectedIndex;
-       }
-
-       public Integer getDefaultIndex() {
-               return defaultIndex;
-       }
-
-       public String getPrompt() {
-               // TODO localize it?
-               return prompt;
-       }
-
-       public void setPrompt(String prompt) {
-               this.prompt = prompt;
-       }
-
-       public List<Locale> getAvailableLocales() {
-               return availableLocales;
-       }
-
-       public static void main(String[] args) {
-               for (String isoL : Locale.getISOLanguages()) {
-                       Locale locale = new Locale(isoL);
-                       System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t"
-                                       + locale.getDisplayLanguage(locale));
-               }
-       }
-
-}
diff --git a/org.argeo.util/src/org/argeo/util/LocaleChoice.java b/org.argeo.util/src/org/argeo/util/LocaleChoice.java
new file mode 100644 (file)
index 0000000..aaf719d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.security.auth.callback.LanguageCallback;
+
+/** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */
+public class LocaleChoice {
+       private List<Locale> availableLocales = new ArrayList<Locale>();
+
+       private Integer selectedIndex = null;
+       private Integer defaultIndex = null;
+
+       // public LocaleCallback(Integer defaultIndex, List<Locale>
+       // availableLocales) {
+       // this.availableLocales = Collections
+       // .unmodifiableList(new ArrayList<Locale>(availableLocales));
+       // this.defaultIndex = defaultIndex;
+       // this.selectedIndex = defaultIndex;
+       // }
+
+       /**
+        * Convenience constructor based on a comma separated list of iso codes (en,
+        * en_US, fr_CA, etc.). Default selection is default locale.
+        */
+       public LocaleChoice(String locales, Locale defaultLocale) {
+               if (locales == null || locales.trim().equals(""))
+                       return;
+               String[] codes = locales.split(",");
+               for (int i = 0; i < codes.length; i++) {
+                       String code = codes[i];
+                       // variant not supported
+                       int indexUnd = code.indexOf("_");
+                       Locale locale;
+                       if (indexUnd > 0) {
+                               String language = code.substring(0, indexUnd);
+                               String country = code.substring(indexUnd + 1);
+                               locale = new Locale(language, country);
+                       } else {
+                               locale = new Locale(code);
+                       }
+                       availableLocales.add(locale);
+                       if (locale.equals(defaultLocale))
+                               defaultIndex = i;
+               }
+
+               if (defaultIndex == null)
+                       defaultIndex = 0;
+
+               this.selectedIndex = defaultIndex;
+       }
+
+       public String[] getSupportedLocalesLabels() {
+               String[] labels = new String[availableLocales.size()];
+               for (int i = 0; i < availableLocales.size(); i++) {
+                       Locale locale = availableLocales.get(i);
+                       if (locale.getCountry().equals(""))
+                               labels[i] = locale.getDisplayLanguage(locale) + " ["
+                                               + locale.getLanguage() + "]";
+                       else
+                               labels[i] = locale.getDisplayLanguage(locale) + " ("
+                                               + locale.getDisplayCountry(locale) + ") ["
+                                               + locale.getLanguage() + "_" + locale.getCountry()
+                                               + "]";
+
+               }
+               return labels;
+       }
+
+       public Locale getSelectedLocale() {
+               if (selectedIndex == null)
+                       return null;
+               return availableLocales.get(selectedIndex);
+       }
+
+       public void setSelectedIndex(Integer selectedIndex) {
+               this.selectedIndex = selectedIndex;
+       }
+
+       public Integer getDefaultIndex() {
+               return defaultIndex;
+       }
+
+       public List<Locale> getAvailableLocales() {
+               return availableLocales;
+       }
+
+       public Locale getDefaultLocale() {
+               return availableLocales.get(getDefaultIndex());
+       }
+
+       public static void main(String[] args) {
+               for (String isoL : Locale.getISOLanguages()) {
+                       Locale locale = new Locale(isoL);
+                       System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t"
+                                       + locale.getDisplayLanguage(locale));
+               }
+       }
+
+}