History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/awt/im/InputMethodManager.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/awt/im/InputMethodManager.java+806−0
@@ -0,0 +1,806 @@
1/*
2 * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.awt.im;
27
28import java.awt.AWTException;
29import java.awt.CheckboxMenuItem;
30import java.awt.Component;
31import java.awt.Dialog;
32import java.awt.EventQueue;
33import java.awt.Frame;
34import java.awt.PopupMenu;
35import java.awt.Menu;
36import java.awt.MenuItem;
37import java.awt.Toolkit;
38import sun.awt.AppContext;
39import java.awt.event.ActionEvent;
40import java.awt.event.ActionListener;
41import java.awt.event.InvocationEvent;
42import java.awt.im.spi.InputMethodDescriptor;
43import java.lang.reflect.InvocationTargetException;
44import java.security.AccessController;
45import java.security.PrivilegedAction;
46import java.security.PrivilegedActionException;
47import java.security.PrivilegedExceptionAction;
48import java.util.Hashtable;
49import java.util.Iterator;
50import java.util.Locale;
51import java.util.ServiceLoader;
52import java.util.Vector;
53import java.util.Set;
54import java.util.prefs.BackingStoreException;
55import java.util.prefs.Preferences;
56import sun.awt.InputMethodSupport;
57import sun.awt.SunToolkit;
58
59/**
60 * <code>InputMethodManager</code> is an abstract class that manages the input
61 * method environment of JVM. There is only one <code>InputMethodManager</code>
62 * instance in JVM that is executed under a separate daemon thread.
63 * <code>InputMethodManager</code> performs the following:
64 * <UL>
65 * <LI>
66 * Keeps track of the current input context.</LI>
67 *
68 * <LI>
69 * Provides a user interface to switch input methods and notifies the current
70 * input context about changes made from the user interface.</LI>
71 * </UL>
72 *
73 * The mechanism for supporting input method switch is as follows. (Note that
74 * this may change in future releases.)
75 *
76 * <UL>
77 * <LI>
78 * One way is to use platform-dependent window manager's menu (known as the <I>Window
79 * menu </I>in Motif and the <I>System menu</I> or <I>Control menu</I> in
80 * Win32) on each window which is popped up by clicking the left top box of
81 * a window (known as <I>Window menu button</I> in Motif and <I>System menu
82 * button</I> in Win32). This happens to be common in both Motif and Win32.</LI>
83 *
84 * <LI>
85 * When more than one input method descriptor can be found or the only input
86 * method descriptor found supports multiple locales, a menu item
87 * is added to the window (manager) menu. This item label is obtained invoking
88 * <code>getTriggerMenuString()</code>. If null is returned by this method, it
89 * means that there is only input method or none in the environment. Frame and Dialog
90 * invoke this method.</LI>
91 *
92 * <LI>
93 * This menu item means a trigger switch to the user to pop up a selection
94 * menu.</LI>
95 *
96 * <LI>
97 * When the menu item of the window (manager) menu has been selected by the
98 * user, Frame/Dialog invokes <code>notifyChangeRequest()</code> to notify
99 * <code>InputMethodManager</code> that the user wants to switch input methods.</LI>
100 *
101 * <LI>
102 * <code>InputMethodManager</code> displays a pop-up menu to choose an input method.</LI>
103 *
104 * <LI>
105 * <code>InputMethodManager</code> notifies the current <code>InputContext</code> of
106 * the selected <code>InputMethod</code>.</LI>
107 * </UL>
108 *
109 * <UL>
110 * <LI>
111 * The other way is to use user-defined hot key combination to show the pop-up menu to
112 * choose an input method. This is useful for the platforms which do not provide a
113 * way to add a menu item in the window (manager) menu.</LI>
114 *
115 * <LI>
116 * When the hot key combination is typed by the user, the component which has the input
117 * focus invokes <code>notifyChangeRequestByHotKey()</code> to notify
118 * <code>InputMethodManager</code> that the user wants to switch input methods.</LI>
119 *
120 * <LI>
121 * This results in a popup menu and notification to the current input context,
122 * as above.</LI>
123 * </UL>
124 *
125 * @see java.awt.im.spi.InputMethod
126 * @see sun.awt.im.InputContext
127 * @see sun.awt.im.InputMethodAdapter
128 * @author JavaSoft International
129 */
130
131public abstract class InputMethodManager {
132
133 /**
134 * InputMethodManager thread name
135 */
136 private static final String threadName = "AWT-InputMethodManager";
137
138 /**
139 * Object for global locking
140 */
141 private static final Object LOCK = new Object();
142
143 /**
144 * The InputMethodManager instance
145 */
146 private static InputMethodManager inputMethodManager;
147
148 /**
149 * Returns the instance of InputMethodManager. This method creates
150 * the instance that is unique in the Java VM if it has not been
151 * created yet.
152 *
153 * @return the InputMethodManager instance
154 */
155 public static final InputMethodManager getInstance() {
156 if (inputMethodManager != null) {
157 return inputMethodManager;
158 }
159 synchronized(LOCK) {
160 if (inputMethodManager == null) {
161 ExecutableInputMethodManager imm = new ExecutableInputMethodManager();
162
163 // Initialize the input method manager and start a
164 // daemon thread if the user has multiple input methods
165 // to choose from. Otherwise, just keep the instance.
166 if (imm.hasMultipleInputMethods()) {
167 imm.initialize();
168 Thread immThread = new Thread(imm, threadName);
169 immThread.setDaemon(true);
170 immThread.setPriority(Thread.NORM_PRIORITY + 1);
171 immThread.start();
172 }
173 inputMethodManager = imm;
174 }
175 }
176 return inputMethodManager;
177 }
178
179 /**
180 * Gets a string for the trigger menu item that should be added to
181 * the window manager menu. If no need to display the trigger menu
182 * item, null is returned.
183 */
184 public abstract String getTriggerMenuString();
185
186 /**
187 * Notifies InputMethodManager that input method change has been
188 * requested by the user. This notification triggers a popup menu
189 * for user selection.
190 *
191 * @param comp Component that has accepted the change
192 * request. This component has to be a Frame or Dialog.
193 */
194 public abstract void notifyChangeRequest(Component comp);
195
196 /**
197 * Notifies InputMethodManager that input method change has been
198 * requested by the user using the hot key combination. This
199 * notification triggers a popup menu for user selection.
200 *
201 * @param comp Component that has accepted the change
202 * request. This component has the input focus.
203 */
204 public abstract void notifyChangeRequestByHotKey(Component comp);
205
206 /**
207 * Sets the current input context so that it will be notified
208 * of input method changes initiated from the user interface.
209 * Set to real input context when activating; to null when
210 * deactivating.
211 */
212 abstract void setInputContext(InputContext inputContext);
213
214 /**
215 * Tries to find an input method locator for the given locale.
216 * Returns null if no available input method locator supports
217 * the locale.
218 */
219 abstract InputMethodLocator findInputMethod(Locale forLocale);
220
221 /**
222 * Gets the default keyboard locale of the underlying operating system.
223 */
224 abstract Locale getDefaultKeyboardLocale();
225
226 /**
227 * Returns whether multiple input methods are available or not
228 */
229 abstract boolean hasMultipleInputMethods();
230
231}
232
233/**
234 * <code>ExecutableInputMethodManager</code> is the implementation of the
235 * <code>InputMethodManager</code> class. It is runnable as a separate
236 * thread in the AWT environment.&nbsp;
237 * <code>InputMethodManager.getInstance()</code> creates an instance of
238 * <code>ExecutableInputMethodManager</code> and executes it as a deamon
239 * thread.
240 *
241 * @see InputMethodManager
242 */
243class ExecutableInputMethodManager extends InputMethodManager
244 implements Runnable
245{
246 // the input context that's informed about selections from the user interface
247 private InputContext currentInputContext;
248
249 // Menu item string for the trigger menu.
250 private String triggerMenuString;
251
252 // popup menu for selecting an input method
253 private InputMethodPopupMenu selectionMenu;
254 private static String selectInputMethodMenuTitle;
255
256 // locator and name of host adapter
257 private InputMethodLocator hostAdapterLocator;
258
259 // locators for Java input methods
260 private int javaInputMethodCount; // number of Java input methods found
261 private Vector<InputMethodLocator> javaInputMethodLocatorList;
262
263 // component that is requesting input method switch
264 // must be Frame or Dialog
265 private Component requestComponent;
266
267 // input context that is requesting input method switch
268 private InputContext requestInputContext;
269
270 // IM preference stuff
271 private static final String preferredIMNode = "/sun/awt/im/preferredInputMethod";
272 private static final String descriptorKey = "descriptor";
273 private Hashtable preferredLocatorCache = new Hashtable();
274 private Preferences userRoot;
275
276 ExecutableInputMethodManager() {
277
278 // set up host adapter locator
279 Toolkit toolkit = Toolkit.getDefaultToolkit();
280 try {
281 if (toolkit instanceof InputMethodSupport) {
282 InputMethodDescriptor hostAdapterDescriptor =
283 ((InputMethodSupport)toolkit)
284 .getInputMethodAdapterDescriptor();
285 if (hostAdapterDescriptor != null) {
286 hostAdapterLocator = new InputMethodLocator(hostAdapterDescriptor, null, null);
287 }
288 }
289 } catch (AWTException e) {
290 // if we can't get a descriptor, we'll just have to do without native input methods
291 }
292
293 javaInputMethodLocatorList = new Vector<InputMethodLocator>();
294 initializeInputMethodLocatorList();
295 }
296
297 synchronized void initialize() {
298 selectInputMethodMenuTitle = Toolkit.getProperty("AWT.InputMethodSelectionMenu", "Select Input Method");
299
300 triggerMenuString = selectInputMethodMenuTitle;
301 }
302
303 public void run() {
304 // If there are no multiple input methods to choose from, wait forever
305 while (!hasMultipleInputMethods()) {
306 try {
307 synchronized (this) {
308 wait();
309 }
310 } catch (InterruptedException e) {
311 }
312 }
313
314 // Loop for processing input method change requests
315 while (true) {
316 waitForChangeRequest();
317 initializeInputMethodLocatorList();
318 try {
319 if (requestComponent != null) {
320 showInputMethodMenuOnRequesterEDT(requestComponent);
321 } else {
322 // show the popup menu within the event thread
323 EventQueue.invokeAndWait(new Runnable() {
324 public void run() {
325 showInputMethodMenu();
326 }
327 });
328 }
329 } catch (InterruptedException ie) {
330 } catch (InvocationTargetException ite) {
331 // should we do anything under these exceptions?
332 }
333 }
334 }
335
336 // Shows Input Method Menu on the EDT of requester component
337 // to avoid side effects. See 6544309.
338 private void showInputMethodMenuOnRequesterEDT(Component requester)
339 throws InterruptedException, InvocationTargetException {
340
341 if (requester == null){
342 return;
343 }
344
345 class AWTInvocationLock {}
346 Object lock = new AWTInvocationLock();
347
348 InvocationEvent event =
349 new InvocationEvent(requester,
350 new Runnable() {
351 public void run() {
352 showInputMethodMenu();
353 }
354 },
355 lock,
356 true);
357
358 AppContext requesterAppContext = SunToolkit.targetToAppContext(requester);
359 synchronized (lock) {
360 SunToolkit.postEvent(requesterAppContext, event);
361 while (!event.isDispatched()) {
362 lock.wait();
363 }
364 }
365
366 Throwable eventThrowable = event.getThrowable();
367 if (eventThrowable != null) {
368 throw new InvocationTargetException(eventThrowable);
369 }
370 }
371
372 void setInputContext(InputContext inputContext) {
373 if (currentInputContext != null && inputContext != null) {
374 // don't throw this exception until 4237852 is fixed
375 // throw new IllegalStateException("Can't have two active InputContext at the same time");
376 }
377 currentInputContext = inputContext;
378 }
379
380 public synchronized void notifyChangeRequest(Component comp) {
381 if (!(comp instanceof Frame || comp instanceof Dialog))
382 return;
383
384 // if busy with the current request, ignore this request.
385 if (requestComponent != null)
386 return;
387
388 requestComponent = comp;
389 notify();
390 }
391
392 public synchronized void notifyChangeRequestByHotKey(Component comp) {
393 while (!(comp instanceof Frame || comp instanceof Dialog)) {
394 if (comp == null) {
395 // no Frame or Dialog found in containment hierarchy.
396 return;
397 }
398 comp = comp.getParent();
399 }
400
401 notifyChangeRequest(comp);
402 }
403
404 public String getTriggerMenuString() {
405 return triggerMenuString;
406 }
407
408 /*
409 * Returns true if the environment indicates there are multiple input methods
410 */
411 boolean hasMultipleInputMethods() {
412 return ((hostAdapterLocator != null) && (javaInputMethodCount > 0)
413 || (javaInputMethodCount > 1));
414 }
415
416 private synchronized void waitForChangeRequest() {
417 try {
418 while (requestComponent == null) {
419 wait();
420 }
421 } catch (InterruptedException e) {
422 }
423 }
424
425 /*
426 * initializes the input method locator list for all
427 * installed input method descriptors.
428 */
429 private void initializeInputMethodLocatorList() {
430 synchronized (javaInputMethodLocatorList) {
431 javaInputMethodLocatorList.clear();
432 try {
433 AccessController.doPrivileged(new PrivilegedExceptionAction() {
434 public Object run() {
435 for (InputMethodDescriptor descriptor :
436 ServiceLoader.loadInstalled(InputMethodDescriptor.class)) {
437 ClassLoader cl = descriptor.getClass().getClassLoader();
438 javaInputMethodLocatorList.add(new InputMethodLocator(descriptor, cl, null));
439 }
440 return null;
441 }
442 });
443 } catch (PrivilegedActionException e) {
444 e.printStackTrace();
445 }
446 javaInputMethodCount = javaInputMethodLocatorList.size();
447 }
448
449 if (hasMultipleInputMethods()) {
450 // initialize preferences
451 if (userRoot == null) {
452 userRoot = getUserRoot();
453 }
454 } else {
455 // indicate to clients not to offer the menu
456 triggerMenuString = null;
457 }
458 }
459
460 private void showInputMethodMenu() {
461
462 if (!hasMultipleInputMethods()) {
463 requestComponent = null;
464 return;
465 }
466
467 // initialize pop-up menu
468 selectionMenu = InputMethodPopupMenu.getInstance(requestComponent, selectInputMethodMenuTitle);
469
470 // we have to rebuild the menu each time because
471 // some input methods (such as IIIMP) may change
472 // their list of supported locales dynamically
473 selectionMenu.removeAll();
474
475 // get information about the currently selected input method
476 // ??? if there's no current input context, what's the point
477 // of showing the menu?
478 String currentSelection = getCurrentSelection();
479
480 // Add menu item for host adapter
481 if (hostAdapterLocator != null) {
482 selectionMenu.addOneInputMethodToMenu(hostAdapterLocator, currentSelection);
483 selectionMenu.addSeparator();
484 }
485
486 // Add menu items for other input methods
487 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
488 InputMethodLocator locator = javaInputMethodLocatorList.get(i);
489 selectionMenu.addOneInputMethodToMenu(locator, currentSelection);
490 }
491
492 synchronized (this) {
493 selectionMenu.addToComponent(requestComponent);
494 requestInputContext = currentInputContext;
495 selectionMenu.show(requestComponent, 60, 80); // TODO: get proper x, y...
496 requestComponent = null;
497 }
498 }
499
500 private String getCurrentSelection() {
501 InputContext inputContext = currentInputContext;
502 if (inputContext != null) {
503 InputMethodLocator locator = inputContext.getInputMethodLocator();
504 if (locator != null) {
505 return locator.getActionCommandString();
506 }
507 }
508 return null;
509 }
510
511 synchronized void changeInputMethod(String choice) {
512 InputMethodLocator locator = null;
513
514 String inputMethodName = choice;
515 String localeString = null;
516 int index = choice.indexOf('\n');
517 if (index != -1) {
518 localeString = choice.substring(index + 1);
519 inputMethodName = choice.substring(0, index);
520 }
521 if (hostAdapterLocator.getActionCommandString().equals(inputMethodName)) {
522 locator = hostAdapterLocator;
523 } else {
524 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
525 InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
526 String name = candidate.getActionCommandString();
527 if (name.equals(inputMethodName)) {
528 locator = candidate;
529 break;
530 }
531 }
532 }
533
534 if (locator != null && localeString != null) {
535 String language = "", country = "", variant = "";
536 int postIndex = localeString.indexOf('_');
537 if (postIndex == -1) {
538 language = localeString;
539 } else {
540 language = localeString.substring(0, postIndex);
541 int preIndex = postIndex + 1;
542 postIndex = localeString.indexOf('_', preIndex);
543 if (postIndex == -1) {
544 country = localeString.substring(preIndex);
545 } else {
546 country = localeString.substring(preIndex, postIndex);
547 variant = localeString.substring(postIndex + 1);
548 }
549 }
550 Locale locale = new Locale(language, country, variant);
551 locator = locator.deriveLocator(locale);
552 }
553
554 if (locator == null)
555 return;
556
557 // tell the input context about the change
558 if (requestInputContext != null) {
559 requestInputContext.changeInputMethod(locator);
560 requestInputContext = null;
561
562 // remember the selection
563 putPreferredInputMethod(locator);
564 }
565 }
566
567 InputMethodLocator findInputMethod(Locale locale) {
568 // look for preferred input method first
569 InputMethodLocator locator = getPreferredInputMethod(locale);
570 if (locator != null) {
571 return locator;
572 }
573
574 if (hostAdapterLocator != null && hostAdapterLocator.isLocaleAvailable(locale)) {
575 return hostAdapterLocator.deriveLocator(locale);
576 }
577
578 // Update the locator list
579 initializeInputMethodLocatorList();
580
581 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
582 InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
583 if (candidate.isLocaleAvailable(locale)) {
584 return candidate.deriveLocator(locale);
585 }
586 }
587 return null;
588 }
589
590 Locale getDefaultKeyboardLocale() {
591 Toolkit toolkit = Toolkit.getDefaultToolkit();
592 if (toolkit instanceof InputMethodSupport) {
593 return ((InputMethodSupport)toolkit).getDefaultKeyboardLocale();
594 } else {
595 return Locale.getDefault();
596 }
597 }
598
599 /**
600 * Returns a InputMethodLocator object that the
601 * user prefers for the given locale.
602 *
603 * @param locale Locale for which the user prefers the input method.
604 */
605 private synchronized InputMethodLocator getPreferredInputMethod(Locale locale) {
606 InputMethodLocator preferredLocator = null;
607
608 if (!hasMultipleInputMethods()) {
609 // No need to look for a preferred Java input method
610 return null;
611 }
612
613 // look for the cached preference first.
614 preferredLocator = (InputMethodLocator)preferredLocatorCache.get(locale.toString().intern());
615 if (preferredLocator != null) {
616 return preferredLocator;
617 }
618
619 // look for the preference in the user preference tree
620 String nodePath = findPreferredInputMethodNode(locale);
621 String descriptorName = readPreferredInputMethod(nodePath);
622 Locale advertised;
623
624 // get the locator object
625 if (descriptorName != null) {
626 // check for the host adapter first
627 if (hostAdapterLocator != null &&
628 hostAdapterLocator.getDescriptor().getClass().getName().equals(descriptorName)) {
629 advertised = getAdvertisedLocale(hostAdapterLocator, locale);
630 if (advertised != null) {
631 preferredLocator = hostAdapterLocator.deriveLocator(advertised);
632 preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
633 }
634 return preferredLocator;
635 }
636 // look for Java input methods
637 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
638 InputMethodLocator locator = javaInputMethodLocatorList.get(i);
639 InputMethodDescriptor descriptor = locator.getDescriptor();
640 if (descriptor.getClass().getName().equals(descriptorName)) {
641 advertised = getAdvertisedLocale(locator, locale);
642 if (advertised != null) {
643 preferredLocator = locator.deriveLocator(advertised);
644 preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
645 }
646 return preferredLocator;
647 }
648 }
649
650 // maybe preferred input method information is bogus.
651 writePreferredInputMethod(nodePath, null);
652 }
653
654 return null;
655 }
656
657 private String findPreferredInputMethodNode(Locale locale) {
658 if (userRoot == null) {
659 return null;
660 }
661
662 // create locale node relative path
663 String nodePath = preferredIMNode + "/" + createLocalePath(locale);
664
665 // look for the descriptor
666 while (!nodePath.equals(preferredIMNode)) {
667 try {
668 if (userRoot.nodeExists(nodePath)) {
669 if (readPreferredInputMethod(nodePath) != null) {
670 return nodePath;
671 }
672 }
673 } catch (BackingStoreException bse) {
674 }
675
676 // search at parent's node
677 nodePath = nodePath.substring(0, nodePath.lastIndexOf('/'));
678 }
679
680 return null;
681 }
682
683 private String readPreferredInputMethod(String nodePath) {
684 if ((userRoot == null) || (nodePath == null)) {
685 return null;
686 }
687
688 return userRoot.node(nodePath).get(descriptorKey, null);
689 }
690
691 /**
692 * Writes the preferred input method descriptor class name into
693 * the user's Preferences tree in accordance with the given locale.
694 *
695 * @param inputMethodLocator input method locator to remember.
696 */
697 private synchronized void putPreferredInputMethod(InputMethodLocator locator) {
698 InputMethodDescriptor descriptor = locator.getDescriptor();
699 Locale preferredLocale = locator.getLocale();
700
701 if (preferredLocale == null) {
702 // check available locales of the input method
703 try {
704 Locale[] availableLocales = descriptor.getAvailableLocales();
705 if (availableLocales.length == 1) {
706 preferredLocale = availableLocales[0];
707 } else {
708 // there is no way to know which locale is the preferred one, so do nothing.
709 return;
710 }
711 } catch (AWTException ae) {
712 // do nothing here, either.
713 return;
714 }
715 }
716
717 // for regions that have only one language, we need to regard
718 // "xx_YY" as "xx" when putting the preference into tree
719 if (preferredLocale.equals(Locale.JAPAN)) {
720 preferredLocale = Locale.JAPANESE;
721 }
722 if (preferredLocale.equals(Locale.KOREA)) {
723 preferredLocale = Locale.KOREAN;
724 }
725 if (preferredLocale.equals(new Locale("th", "TH"))) {
726 preferredLocale = new Locale("th");
727 }
728
729 // obtain node
730 String path = preferredIMNode + "/" + createLocalePath(preferredLocale);
731
732 // write in the preference tree
733 writePreferredInputMethod(path, descriptor.getClass().getName());
734 preferredLocatorCache.put(preferredLocale.toString().intern(),
735 locator.deriveLocator(preferredLocale));
736
737 return;
738 }
739
740 private String createLocalePath(Locale locale) {
741 String language = locale.getLanguage();
742 String country = locale.getCountry();
743 String variant = locale.getVariant();
744 String localePath = null;
745 if (!variant.equals("")) {
746 localePath = "_" + language + "/_" + country + "/_" + variant;
747 } else if (!country.equals("")) {
748 localePath = "_" + language + "/_" + country;
749 } else {
750 localePath = "_" + language;
751 }
752
753 return localePath;
754 }
755
756 private void writePreferredInputMethod(String path, String descriptorName) {
757 if (userRoot != null) {
758 Preferences node = userRoot.node(path);
759
760 // record it
761 if (descriptorName != null) {
762 node.put(descriptorKey, descriptorName);
763 } else {
764 node.remove(descriptorKey);
765 }
766 }
767 }
768
769 private Preferences getUserRoot() {
770 return (Preferences)AccessController.doPrivileged(new PrivilegedAction() {
771 public Object run() {
772 return Preferences.userRoot();
773 }
774 });
775 }
776
777 private Locale getAdvertisedLocale(InputMethodLocator locator, Locale locale) {
778 Locale advertised = null;
779
780 if (locator.isLocaleAvailable(locale)) {
781 advertised = locale;
782 } else if (locale.getLanguage().equals("ja")) {
783 // for Japanese, Korean, and Thai, check whether the input method supports
784 // language or language_COUNTRY.
785 if (locator.isLocaleAvailable(Locale.JAPAN)) {
786 advertised = Locale.JAPAN;
787 } else if (locator.isLocaleAvailable(Locale.JAPANESE)) {
788 advertised = Locale.JAPANESE;
789 }
790 } else if (locale.getLanguage().equals("ko")) {
791 if (locator.isLocaleAvailable(Locale.KOREA)) {
792 advertised = Locale.KOREA;
793 } else if (locator.isLocaleAvailable(Locale.KOREAN)) {
794 advertised = Locale.KOREAN;
795 }
796 } else if (locale.getLanguage().equals("th")) {
797 if (locator.isLocaleAvailable(new Locale("th", "TH"))) {
798 advertised = new Locale("th", "TH");
799 } else if (locator.isLocaleAvailable(new Locale("th"))) {
800 advertised = new Locale("th");
801 }
802 }
803
804 return advertised;
805 }
806}