Source Code Cross Referenced for CmsLocaleManager.java in  » Content-Management-System » opencms » org » opencms » i18n » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » opencms » org.opencms.i18n 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * File   : $Source: /usr/local/cvs/opencms/src/org/opencms/i18n/CmsLocaleManager.java,v $
003:         * Date   : $Date: 2008-02-27 12:05:47 $
004:         * Version: $Revision: 1.56 $
005:         *
006:         * This library is part of OpenCms -
007:         * the Open Source Content Management System
008:         *
009:         * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010:         *
011:         * This library is free software; you can redistribute it and/or
012:         * modify it under the terms of the GNU Lesser General Public
013:         * License as published by the Free Software Foundation; either
014:         * version 2.1 of the License, or (at your option) any later version.
015:         *
016:         * This library is distributed in the hope that it will be useful,
017:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
018:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019:         * Lesser General Public License for more details.
020:         *
021:         * For further information about Alkacon Software GmbH, please see the
022:         * company website: http://www.alkacon.com
023:         *
024:         * For further information about OpenCms, please see the
025:         * project website: http://www.opencms.org
026:         * 
027:         * You should have received a copy of the GNU Lesser General Public
028:         * License along with this library; if not, write to the Free Software
029:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
030:         */
031:
032:        package org.opencms.i18n;
033:
034:        import org.opencms.file.CmsObject;
035:        import org.opencms.file.CmsProject;
036:        import org.opencms.file.CmsPropertyDefinition;
037:        import org.opencms.file.CmsResource;
038:        import org.opencms.file.CmsUser;
039:        import org.opencms.main.CmsEvent;
040:        import org.opencms.main.CmsException;
041:        import org.opencms.main.CmsLog;
042:        import org.opencms.main.I_CmsEventListener;
043:        import org.opencms.main.OpenCms;
044:        import org.opencms.util.CmsStringUtil;
045:
046:        import java.util.ArrayList;
047:        import java.util.Collection;
048:        import java.util.Iterator;
049:        import java.util.List;
050:        import java.util.Locale;
051:
052:        import javax.servlet.http.HttpServletRequest;
053:
054:        import org.apache.commons.logging.Log;
055:
056:        /**
057:         * Manages the locales configured for this OpenCms installation.<p>
058:         * 
059:         * Locale configuration is done in the configuration file <code>opencms-system.xml</code>
060:         * in the <code>opencms/system/internationalization</code> node and it's sub-nodes.<p>
061:         * 
062:         * @author Carsten Weinholz 
063:         * @author Alexander Kandzior 
064:         * 
065:         * @version $Revision: 1.56 $ 
066:         * 
067:         * @since 6.0.0 
068:         */
069:        public class CmsLocaleManager implements  I_CmsEventListener {
070:
071:            /** Runtime property name for locale handler. */
072:            public static final String LOCALE_HANDLER = "class_locale_handler";
073:
074:            /** Request parameter to force encoding selection. */
075:            public static final String PARAMETER_ENCODING = "__encoding";
076:
077:            /** Request parameter to force locale selection. */
078:            public static final String PARAMETER_LOCALE = "__locale";
079:
080:            /** The log object for this class. */
081:            private static final Log LOG = CmsLog
082:                    .getLog(CmsLocaleManager.class);
083:
084:            /** The default locale, this is the first configured locale. */
085:            private static Locale m_defaultLocale;
086:
087:            /** The set of available locale names. */
088:            private List m_availableLocales;
089:
090:            /** The default locale names (must be a subset of the available locale names). */
091:            private List m_defaultLocales;
092:
093:            /** Indicates if the locale manager is fully initialized. */
094:            private boolean m_initialized;
095:
096:            /** The configured locale handler. */
097:            private I_CmsLocaleHandler m_localeHandler;
098:
099:            /**
100:             * Initializes a new CmsLocaleManager, called from the configuration.<p>
101:             */
102:            public CmsLocaleManager() {
103:
104:                setDefaultLocale();
105:                m_availableLocales = new ArrayList();
106:                m_defaultLocales = new ArrayList();
107:                m_localeHandler = new CmsDefaultLocaleHandler();
108:                if (CmsLog.INIT.isInfoEnabled()) {
109:                    CmsLog.INIT.info(Messages.get().getBundle().key(
110:                            Messages.INIT_I18N_CONFIG_START_0));
111:                }
112:                // register this object as event listener
113:                OpenCms.addCmsEventListener(this ,
114:                        new int[] { I_CmsEventListener.EVENT_CLEAR_CACHES });
115:            }
116:
117:            /**
118:             * Initializes a new CmsLocaleManager, used for OpenCms runlevel 1 (unit tests) only.<p>
119:             * 
120:             * @param defaultLocale the default locale to use
121:             */
122:            public CmsLocaleManager(Locale defaultLocale) {
123:
124:                setDefaultLocale();
125:                m_initialized = false;
126:
127:                m_availableLocales = new ArrayList();
128:                m_defaultLocales = new ArrayList();
129:                m_localeHandler = new CmsDefaultLocaleHandler();
130:
131:                m_defaultLocale = defaultLocale;
132:                m_defaultLocales.add(defaultLocale);
133:                m_availableLocales.add(defaultLocale);
134:            }
135:
136:            /**
137:             * Required for setting the default locale on the first possible time.<p>
138:             */
139:            static {
140:                setDefaultLocale();
141:            }
142:
143:            /**
144:             * Returns the default locale configured in <code>opencms-system.xml</code>, 
145:             * that is the first locale from the list provided
146:             * in the <code>opencms/system/internationalization/localesdefault</code> node.<p>
147:             *
148:             * @return the default locale configured in <code>opencms-system.xml</code>
149:             */
150:            public static Locale getDefaultLocale() {
151:
152:                return m_defaultLocale;
153:            }
154:
155:            /**
156:             * Returns a locale created from the given full name.<p>
157:             * 
158:             * The full name must consist of language code, 
159:             * country code(optional), variant(optional) separated by "_".<p>
160:             * 
161:             * This method will always return a valid Locale!
162:             * If the provided locale name is not valid (i.e. leads to an Exception
163:             * when trying to create the Locale, then the configured default Locale is returned.<p> 
164:             * 
165:             * @param localeName the full locale name
166:             * @return the locale or <code>null</code> if not available
167:             */
168:            public static Locale getLocale(String localeName) {
169:
170:                if (CmsStringUtil.isEmpty(localeName)) {
171:                    return getDefaultLocale();
172:                }
173:                Locale locale = null;
174:                if (OpenCms.getMemoryMonitor() != null) {
175:                    // this may be used AFTER shutdown
176:                    locale = OpenCms.getMemoryMonitor().getCachedLocale(
177:                            localeName);
178:                }
179:                if (locale != null) {
180:                    return locale;
181:                }
182:                try {
183:                    String[] localeNames = CmsStringUtil.splitAsArray(
184:                            localeName, '_');
185:                    locale = new Locale(localeNames[0],
186:                            (localeNames.length > 1) ? localeNames[1] : "",
187:                            (localeNames.length > 2) ? localeNames[2] : "");
188:                } catch (Throwable t) {
189:                    LOG
190:                            .debug(Messages.get().getBundle().key(
191:                                    Messages.LOG_CREATE_LOCALE_FAILED_1,
192:                                    localeName), t);
193:                    // map this error to the default locale
194:                    locale = getDefaultLocale();
195:                }
196:                if (OpenCms.getMemoryMonitor() != null) {
197:                    // this may be used AFTER shutdown
198:                    OpenCms.getMemoryMonitor().cacheLocale(localeName, locale);
199:                }
200:                return locale;
201:            }
202:
203:            /**
204:             * Returns the locale names from the given List of locales as a comma separated String.<p>
205:             * 
206:             * For example, if the input List contains <code>{@link Locale#ENGLISH}</code> and 
207:             * <code>{@link Locale#GERMANY}</code>, the result will be <code>"en, de_DE"</code>.<p>
208:             * 
209:             * An empty String is returned if the input is <code>null</code>, or contains no elements.<p>
210:             * 
211:             * @param localeNames the locale names to generate a String from
212:             * 
213:             * @return the locale names from the given List of locales as a comma separated String
214:             */
215:            public static String getLocaleNames(List localeNames) {
216:
217:                StringBuffer result = new StringBuffer();
218:                if (localeNames != null) {
219:                    Iterator i = localeNames.iterator();
220:                    while (i.hasNext()) {
221:                        result.append(i.next().toString());
222:                        if (i.hasNext()) {
223:                            result.append(", ");
224:                        }
225:                    }
226:                }
227:                return result.toString();
228:            }
229:
230:            /**
231:             * Returns a List of locales from an array of locale names.<p>
232:             * 
233:             * @param localeNames array of locale names
234:             * @return a List of locales derived from the given locale names
235:             */
236:            public static List getLocales(List localeNames) {
237:
238:                List result = new ArrayList(localeNames.size());
239:                for (int i = 0; i < localeNames.size(); i++) {
240:                    result.add(getLocale(localeNames.get(i).toString().trim()));
241:                }
242:                return result;
243:            }
244:
245:            /**
246:             * Returns a List of locales from a comma-separated string of locale names.<p>
247:             * 
248:             * @param localeNames a comma-separated string of locale names
249:             * @return a List of locales derived from the given locale names
250:             */
251:            public static List getLocales(String localeNames) {
252:
253:                if (localeNames == null) {
254:                    return null;
255:                }
256:                return getLocales(CmsStringUtil.splitAsList(localeNames, ','));
257:            }
258:
259:            /**
260:             * Returns the content encoding set for the given resource.<p>
261:             * 
262:             * The content encoding is controlled by the property {@link CmsPropertyDefinition#PROPERTY_CONTENT_ENCODING},
263:             * which can be set on the resource or on a parent folder for all resources in this folder.<p>
264:             * 
265:             * In case no encoding has been set, the default encoding from 
266:             * {@link org.opencms.main.CmsSystemInfo#getDefaultEncoding()} is returned.<p> 
267:             * 
268:             * @param cms the current OpenCms user context
269:             * @param res the resource to read the encoding for
270:             * 
271:             * @return the content encoding set for the given resource
272:             */
273:            public static final String getResourceEncoding(CmsObject cms,
274:                    CmsResource res) {
275:
276:                String encoding = null;
277:                // get the encoding
278:                try {
279:                    encoding = cms.readPropertyObject(res,
280:                            CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING,
281:                            true).getValue();
282:                    if (encoding != null) {
283:                        encoding = CmsEncoder.lookupEncoding(encoding.trim(),
284:                                encoding);
285:                    }
286:                } catch (CmsException e) {
287:                    if (LOG.isInfoEnabled()) {
288:                        LOG.info(Messages.get().getBundle().key(
289:                                Messages.ERR_READ_ENCODING_PROP_1,
290:                                res.getRootPath()), e);
291:                    }
292:                }
293:                if (encoding == null) {
294:                    encoding = OpenCms.getSystemInfo().getDefaultEncoding();
295:                }
296:                return encoding;
297:            }
298:
299:            /**
300:             * Sets the default locale of the Java VM to <code>{@link Locale#ENGLISH}</code> if the 
301:             * current default has any other language then English set.<p>
302:             *
303:             * This is required because otherwise the default (English) resource bundles 
304:             * would not be displayed for the English locale if a translated default locale exists.<p>
305:             * 
306:             * Here's an example of how this issues shows up:
307:             * On a German server, the default locale usually is <code>{@link Locale#GERMAN}</code>.
308:             * All English translations for OpenCms are located in the "default" message files, for example 
309:             * <code>org.opencms.i18n.message.properties</code>. If the German localization is installed, it will be
310:             * located in <code>org.opencms.i18n.message_de.properties</code>. If user has English selected
311:             * as his locale, the default Java lookup mechanism first tries to find 
312:             * <code>org.opencms.i18n.message_en.properties</code>. However, this file does not exist, since the
313:             * English localization is kept in the default file. Next, the Java lookup mechanism tries to find the servers
314:             * default locale, which in this example is German. Since there is a German message file, the Java lookup mechanism
315:             * is finished and uses this German localization, not the default file. Therefore the 
316:             * user get the German localization, not the English one.
317:             * Setting the default locale explicitly to English avoids this issue.<p>
318:             */
319:            private static void setDefaultLocale() {
320:
321:                // set the default locale to english
322:                // this is required because otherwise the default (english) resource bundles 
323:                // would not be displayed for the english locale if a translated locale exists
324:
325:                Locale oldLocale = Locale.getDefault();
326:                if (!(Locale.ENGLISH.getLanguage().equals(oldLocale
327:                        .getLanguage()))) {
328:                    // default language is not English
329:                    try {
330:                        Locale.setDefault(Locale.ENGLISH);
331:                        if (CmsLog.INIT.isInfoEnabled()) {
332:                            CmsLog.INIT.info(Messages.get().getBundle().key(
333:                                    Messages.INIT_I18N_DEFAULT_LOCALE_2,
334:                                    Locale.ENGLISH, oldLocale));
335:                        }
336:                    } catch (Exception e) {
337:                        // any Exception: the locale has not been changed, so there may be issues with the English
338:                        // localization but OpenCms will run in general
339:                        CmsLog.INIT.error(Messages.get().getBundle().key(
340:                                Messages.LOG_UNABLE_TO_SET_DEFAULT_LOCALE_2,
341:                                Locale.ENGLISH, oldLocale), e);
342:                    }
343:                } else {
344:                    if (CmsLog.INIT.isInfoEnabled()) {
345:                        CmsLog.INIT.info(Messages.get().getBundle().key(
346:                                Messages.INIT_I18N_KEEPING_DEFAULT_LOCALE_1,
347:                                oldLocale));
348:                    }
349:                }
350:
351:                // initialize the static member with the new default 
352:                m_defaultLocale = Locale.getDefault();
353:            }
354:
355:            /**
356:             * Adds a locale to the list of available locales.<p>
357:             * 
358:             * @param localeName the locale to add
359:             */
360:            public void addAvailableLocale(String localeName) {
361:
362:                Locale locale = getLocale(localeName);
363:                // add full variation (language / country / variant)
364:                if (!m_availableLocales.contains(locale)) {
365:                    m_availableLocales.add(locale);
366:                    if (CmsLog.INIT.isInfoEnabled()) {
367:                        CmsLog.INIT
368:                                .info(Messages.get().getBundle().key(
369:                                        Messages.INIT_I18N_CONFIG_ADD_LOCALE_1,
370:                                        locale));
371:                    }
372:                }
373:                // add variation with only language and country
374:                locale = new Locale(locale.getLanguage(), locale.getCountry());
375:                if (!m_availableLocales.contains(locale)) {
376:                    m_availableLocales.add(locale);
377:                    if (CmsLog.INIT.isInfoEnabled()) {
378:                        CmsLog.INIT
379:                                .info(Messages.get().getBundle().key(
380:                                        Messages.INIT_I18N_CONFIG_ADD_LOCALE_1,
381:                                        locale));
382:                    }
383:                }
384:                // add variation with language only
385:                locale = new Locale(locale.getLanguage());
386:                if (!m_availableLocales.contains(locale)) {
387:                    m_availableLocales.add(locale);
388:                    if (CmsLog.INIT.isInfoEnabled()) {
389:                        CmsLog.INIT
390:                                .info(Messages.get().getBundle().key(
391:                                        Messages.INIT_I18N_CONFIG_ADD_LOCALE_1,
392:                                        locale));
393:                    }
394:                }
395:            }
396:
397:            /**
398:             * Adds a locale to the list of default locales.<p>
399:             * 
400:             * @param localeName the locale to add
401:             */
402:            public void addDefaultLocale(String localeName) {
403:
404:                Locale locale = getLocale(localeName);
405:                if (!m_defaultLocales.contains(locale)) {
406:                    m_defaultLocales.add(locale);
407:                    if (CmsLog.INIT.isInfoEnabled()) {
408:                        CmsLog.INIT.info(Messages.get().getBundle().key(
409:                                Messages.INIT_I18N_CONFIG_DEFAULT_LOCALE_2,
410:                                new Integer(m_defaultLocales.size()), locale));
411:
412:                    }
413:                }
414:            }
415:
416:            /**
417:             * Implements the CmsEvent interface,
418:             * the locale manager the events to clear 
419:             * the list of cached keys .<p>
420:             *
421:             * @param event CmsEvent that has occurred
422:             */
423:            public void cmsEvent(CmsEvent event) {
424:
425:                switch (event.getType()) {
426:                case I_CmsEventListener.EVENT_CLEAR_CACHES:
427:                    clearCaches();
428:                    break;
429:                default: // no operation
430:                }
431:            }
432:
433:            /**
434:             * Returns the list of available {@link Locale}s configured in <code>opencms-system.xml</code>, 
435:             * in the <code>opencms/system/internationalization/localesconfigured</code> node.<p>
436:             *
437:             * The list of configured available locales contains all locales that are allowed to be used in the VFS,
438:             * for example as languages in XML content files.<p>
439:             * 
440:             * The available locales are a superset of the default locales, see {@link #getDefaultLocales()}.<p>
441:             * 
442:             * It's possible to reduce the system default by setting the propery 
443:             * <code>{@link CmsPropertyDefinition#PROPERTY_AVAILABLE_LOCALES}</code> 
444:             * to a comma separated list of locale names. However, you can not add new available locales, 
445:             * only remove from the configured list.<p>
446:             *
447:             * @return the list of available locale names, e.g. <code>en, de</code>
448:             * 
449:             * @see #getDefaultLocales()
450:             */
451:            public List getAvailableLocales() {
452:
453:                return m_availableLocales;
454:            }
455:
456:            /**
457:             * Returns an array of available locale names for the given resource.<p>
458:             * 
459:             * @param cms the current cms permission object
460:             * @param resourceName the name of the resource
461:             * 
462:             * @return an array of available locale names
463:             * 
464:             * @see #getAvailableLocales()
465:             */
466:            public List getAvailableLocales(CmsObject cms, String resourceName) {
467:
468:                String availableNames = null;
469:                try {
470:                    availableNames = cms.readPropertyObject(resourceName,
471:                            CmsPropertyDefinition.PROPERTY_AVAILABLE_LOCALES,
472:                            true).getValue();
473:                } catch (CmsException exc) {
474:                    // noop
475:                }
476:
477:                List result = null;
478:                if (availableNames != null) {
479:                    result = getAvailableLocales(availableNames);
480:                }
481:                if ((result == null) || (result.size() == 0)) {
482:                    return m_availableLocales;
483:                } else {
484:                    return result;
485:                }
486:            }
487:
488:            /**
489:             * Returns a List of available locales from a comma separated string of locale names.<p>
490:             * 
491:             * All names are filtered against the allowed available locales 
492:             * configured in <code>opencms-system.xml</code>.<P>
493:             * 
494:             * @param names a comma-separated String of locale names
495:             * @return List of locales created from the given locale names
496:             * 
497:             * @see #getAvailableLocales()
498:             */
499:            public List getAvailableLocales(String names) {
500:
501:                return checkLocaleNames(getLocales(names));
502:            }
503:
504:            /**
505:             * Tries to find the given requested locale (eventually simplified) in the collection of available locales, 
506:             * if the requested locale is not found it will return the first match from the given list of default locales.<p>
507:             * 
508:             * @param requestedLocale the requested locale, if this (or a simplified version of it) is available it will be returned
509:             * @param defaults a list of default locales to use in case the requested locale is not available
510:             * @param available the available locales to find a match in
511:             * 
512:             * @return the best matching locale name or null if no name matches
513:             */
514:            public Locale getBestMatchingLocale(Locale requestedLocale,
515:                    List defaults, Collection available) {
516:
517:                if ((available == null) || available.isEmpty()) {
518:                    // no locales are available at all
519:                    return null;
520:                }
521:
522:                // the requested locale is the match we want to find most
523:                if (available.contains(requestedLocale)) {
524:                    // check if the requested locale is directly available
525:                    return requestedLocale;
526:                }
527:                if (requestedLocale.getVariant().length() > 0) {
528:                    // locale has a variant like "en_EN_whatever", try only with language and country 
529:                    Locale check = new Locale(requestedLocale.getLanguage(),
530:                            requestedLocale.getCountry(), "");
531:                    if (available.contains(check)) {
532:                        return check;
533:                    }
534:                }
535:                if (requestedLocale.getCountry().length() > 0) {
536:                    // locale has a country like "en_EN", try only with language
537:                    Locale check = new Locale(requestedLocale.getLanguage(),
538:                            "", "");
539:                    if (available.contains(check)) {
540:                        return check;
541:                    }
542:                }
543:
544:                // available locales do not match the requested locale
545:                if ((defaults == null) || defaults.isEmpty()) {
546:                    // if we have no default locales we are out of luck
547:                    return null;
548:                }
549:
550:                // no match found for the requested locale, return the first match from the default locales
551:                return getFirstMatchingLocale(defaults, available);
552:            }
553:
554:            /**
555:             * Returns the "the" default locale for the given resource.<p>
556:             * 
557:             * It's possible to override the system default (see {@link #getDefaultLocale()}) by setting the property 
558:             * <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> to a comma separated list of locale names.
559:             * This property is inherited from the parent folders.
560:             * This method will return the first locale from that list.<p>
561:             * 
562:             * The default locale must be contained in the set of configured available locales, 
563:             * see {@link #getAvailableLocales()}.
564:             * In case an invalid locale has been set with the property, this locale is ignored and the 
565:             * same result as {@link #getDefaultLocale()} is returned.<p>
566:             * 
567:             * In case the property <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> has not been set
568:             * on the resource or a parent folder,
569:             * this method returns the same result as {@link #getDefaultLocale()}.<p>
570:             * 
571:             * @param cms the current cms permission object
572:             * @param resourceName the name of the resource
573:             * @return an array of default locale names
574:             * 
575:             * @see #getDefaultLocales()
576:             * @see #getDefaultLocales(CmsObject, String)
577:             */
578:            public Locale getDefaultLocale(CmsObject cms, String resourceName) {
579:
580:                List defaultLocales = getDefaultLocales(cms, resourceName);
581:                Locale result;
582:                if (defaultLocales.size() > 0) {
583:                    result = (Locale) defaultLocales.get(0);
584:                } else {
585:                    result = getDefaultLocale();
586:                }
587:                return result;
588:            }
589:
590:            /**
591:             * Returns the list of default {@link Locale}s configured in <code>opencms-system.xml</code>,
592:             * in the <code>opencms/system/internationalization/localesdefault</code> node.<p>
593:             * 
594:             * Since the default locale is always available, the result list will always contain at least one Locale.<p>
595:             * 
596:             * It's possible to override the system default by setting the property 
597:             * <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> to a comma separated list of locale names.
598:             * This property is inherited from the parent folders.<p>
599:             * 
600:             * The default locales must be a subset of the configured available locales, see {@link #getAvailableLocales()}.
601:             * In case an invalid locale has been set with the property, this locale is ignored.<p>
602:             * 
603:             * The default locale names are used as a fallback mechanism in case a locale is requested 
604:             * that can not be found, for example when delivering content form an XML content.<p>
605:             * 
606:             * There is a list of default locales (instead of just one default locale) since there
607:             * are scenarios when one default is not enough. Consider the following example:<i>
608:             * The main default locale is set to "en". An example XML content file contains just one language, 
609:             * in this case "de" and not "en". Now a request is made to the file for the locale "fr". If 
610:             * there would be only one default locale ("en"), we would have to give up. But since we allow more then 
611:             * one default, we can deliver the "de" content instead of a blank page.</I><p>
612:             * 
613:             * @return the list of default locale names, e.g. <code>en, de</code>
614:             * 
615:             * @see #getAvailableLocales()
616:             */
617:            public List getDefaultLocales() {
618:
619:                return m_defaultLocales;
620:            }
621:
622:            /**
623:             * Returns an array of default locales for the given resource.<p>
624:             * 
625:             * Since the default locale is always available, the result list will always contain at least one Locale.<p>
626:             * 
627:             * It's possible to override the system default (see {@link #getDefaultLocales()}) by setting the property 
628:             * <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> to a comma separated list of locale names.
629:             * This property is inherited from the parent folders.<p>
630:             * 
631:             * The default locales must be a subset of the configured available locales, see {@link #getAvailableLocales()}.
632:             * In case an invalid locale has been set with the property, this locale is ignored.<p>
633:             * 
634:             * In case the property <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> has not been set
635:             * on the resource or a parent folder,
636:             * this method returns the same result as {@link #getDefaultLocales()}.<p>
637:             * 
638:             * Use this method in case you need to get all configured default options for a resource,
639:             * if you just need the "the" default locale for a resource, 
640:             * use <code>{@link #getDefaultLocale(CmsObject, String)}</code>.<p>
641:             * 
642:             * @param cms the current cms permission object
643:             * @param resource the resource to read the default locale properties for
644:             * @return an array of default locale names
645:             * 
646:             * @see #getDefaultLocales()
647:             * @see #getDefaultLocale(CmsObject, String)
648:             * @see #getDefaultLocales(CmsObject, String)
649:             * 
650:             * @since 7.0.2
651:             */
652:            public List getDefaultLocales(CmsObject cms, CmsResource resource) {
653:
654:                String defaultNames = null;
655:                try {
656:                    defaultNames = cms.readPropertyObject(resource,
657:                            CmsPropertyDefinition.PROPERTY_LOCALE, true)
658:                            .getValue();
659:                } catch (CmsException e) {
660:                    LOG.warn(Messages.get().getBundle().key(
661:                            Messages.ERR_READ_ENCODING_PROP_1,
662:                            cms.getSitePath(resource)), e);
663:                }
664:                return getDefaultLocales(defaultNames);
665:            }
666:
667:            /**
668:             * Returns an array of default locales for the given resource.<p>
669:             * 
670:             * Since the default locale is always available, the result list will always contain at least one Locale.<p>
671:             * 
672:             * It's possible to override the system default (see {@link #getDefaultLocales()}) by setting the property 
673:             * <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> to a comma separated list of locale names.
674:             * This property is inherited from the parent folders.<p>
675:             * 
676:             * The default locales must be a subset of the configured available locales, see {@link #getAvailableLocales()}.
677:             * In case an invalid locale has been set with the property, this locale is ignored.<p>
678:             * 
679:             * In case the property <code>{@link CmsPropertyDefinition#PROPERTY_LOCALE}</code> has not been set
680:             * on the resource or a parent folder,
681:             * this method returns the same result as {@link #getDefaultLocales()}.<p>
682:             * 
683:             * Use this method in case you need to get all configured default options for a resource,
684:             * if you just need the "the" default locale for a resource, 
685:             * use <code>{@link #getDefaultLocale(CmsObject, String)}</code>.<p>
686:             * 
687:             * @param cms the current cms permission object
688:             * @param resourceName the name of the resource
689:             * @return an array of default locale names
690:             * 
691:             * @see #getDefaultLocales()
692:             * @see #getDefaultLocale(CmsObject, String)
693:             * @see #getDefaultLocales(CmsObject, CmsResource) 
694:             */
695:            public List getDefaultLocales(CmsObject cms, String resourceName) {
696:
697:                String defaultNames = null;
698:                try {
699:                    defaultNames = cms.readPropertyObject(resourceName,
700:                            CmsPropertyDefinition.PROPERTY_LOCALE, true)
701:                            .getValue();
702:                } catch (CmsException e) {
703:                    LOG
704:                            .warn(Messages.get().getBundle().key(
705:                                    Messages.ERR_READ_ENCODING_PROP_1,
706:                                    resourceName), e);
707:                }
708:                return getDefaultLocales(defaultNames);
709:            }
710:
711:            /**
712:             * Returns the first matching locale (eventually simplified) from the available locales.<p>
713:             * 
714:             * In case no match is found, code <code>null</code> is returned.<p>
715:             * 
716:             * @param locales must be an ascending sorted list of locales in order of preference
717:             * @param available the available locales to find a match in
718:             * 
719:             * @return the first precise or simplified match, or <code>null</code> in case no match is found
720:             */
721:            public Locale getFirstMatchingLocale(List locales,
722:                    Collection available) {
723:
724:                Iterator i;
725:                // first try a precise match
726:                i = locales.iterator();
727:                while (i.hasNext()) {
728:                    Locale locale = (Locale) i.next();
729:                    if (available.contains(locale)) {
730:                        // precise match
731:                        return locale;
732:                    }
733:                }
734:
735:                // now try a match only with language and country
736:                i = locales.iterator();
737:                while (i.hasNext()) {
738:                    Locale locale = (Locale) i.next();
739:                    if (locale.getVariant().length() > 0) {
740:                        // the locale has a variant, try to match without the variant
741:                        locale = new Locale(locale.getLanguage(), locale
742:                                .getCountry(), "");
743:                        if (available.contains(locale)) {
744:                            // match
745:                            return locale;
746:                        }
747:                    }
748:                }
749:
750:                // finally try a match only with language
751:                i = locales.iterator();
752:                while (i.hasNext()) {
753:                    Locale locale = (Locale) i.next();
754:                    if (locale.getCountry().length() > 0) {
755:                        // the locale has a country, try to match without the country
756:                        locale = new Locale(locale.getLanguage(), "", "");
757:                        if (available.contains(locale)) {
758:                            // match
759:                            return locale;
760:                        }
761:                    }
762:                }
763:
764:                // no match
765:                return null;
766:            }
767:
768:            /**
769:             * Returns the the appropriate locale/encoding for a request,
770:             * using the "right" locale handler for the given resource.<p>
771:             * 
772:             * Certain system folders (like the Workplace) require a special
773:             * locale handler different from the configured handler.
774:             * Use this method if you want to resolve locales exactly like 
775:             * the system does for a request.<p>
776:             * 
777:             * @param req the current http request
778:             * @param user the current user
779:             * @param project the current project
780:             * @param resource the URI of the requested resource (with full site root added)
781:             * 
782:             * @return the i18n information to use for the given request context
783:             */
784:            public CmsI18nInfo getI18nInfo(HttpServletRequest req,
785:                    CmsUser user, CmsProject project, String resource) {
786:
787:                CmsI18nInfo i18nInfo = null;
788:
789:                // check if this is a request against a Workplace folder
790:                if (OpenCms.getSiteManager().isWorkplaceRequest(req)) {
791:                    // The list of configured localized workplace folders
792:                    List wpLocalizedFolders = OpenCms.getWorkplaceManager()
793:                            .getLocalizedFolders();
794:                    for (int i = wpLocalizedFolders.size() - 1; i >= 0; i--) {
795:                        if (resource.startsWith((String) wpLocalizedFolders
796:                                .get(i))) {
797:                            // use the workplace locale handler for this resource
798:                            i18nInfo = OpenCms.getWorkplaceManager()
799:                                    .getI18nInfo(req, user, project, resource);
800:                            break;
801:                        }
802:                    }
803:                }
804:                if (i18nInfo == null) {
805:                    // use default locale handler
806:                    i18nInfo = m_localeHandler.getI18nInfo(req, user, project,
807:                            resource);
808:                }
809:
810:                // check the request for special parameters overriding the locale handler
811:                Locale locale = null;
812:                String encoding = null;
813:                if (req != null) {
814:                    String localeParam = req
815:                            .getParameter(CmsLocaleManager.PARAMETER_LOCALE);
816:                    // check request for parameters
817:                    if (localeParam != null) {
818:                        // "__locale" parameter found in request
819:                        locale = CmsLocaleManager.getLocale(localeParam);
820:                    }
821:                    // check for "__encoding" parameter in request
822:                    encoding = req
823:                            .getParameter(CmsLocaleManager.PARAMETER_ENCODING);
824:                }
825:
826:                // merge values from request with values from locale handler
827:                if (locale == null) {
828:                    locale = i18nInfo.getLocale();
829:                }
830:                if (encoding == null) {
831:                    encoding = i18nInfo.getEncoding();
832:                }
833:
834:                // still some values might be "null"
835:                if (locale == null) {
836:                    locale = getDefaultLocale();
837:                    if (LOG.isDebugEnabled()) {
838:                        LOG.debug(Messages.get().getBundle().key(
839:                                Messages.LOG_LOCALE_NOT_FOUND_1, locale));
840:                    }
841:                }
842:                if (encoding == null) {
843:                    encoding = OpenCms.getSystemInfo().getDefaultEncoding();
844:                    if (LOG.isDebugEnabled()) {
845:                        LOG.debug(Messages.get().getBundle().key(
846:                                Messages.LOG_ENCODING_NOT_FOUND_1, encoding));
847:                    }
848:                }
849:
850:                // return the merged values
851:                return new CmsI18nInfo(locale, encoding);
852:            }
853:
854:            /**
855:             * Returns the configured locale handler.<p>
856:             * 
857:             * This handler is used to derive the appropriate locale/encoding for a request.<p>
858:             * 
859:             * @return the locale handler
860:             */
861:            public I_CmsLocaleHandler getLocaleHandler() {
862:
863:                return m_localeHandler;
864:            }
865:
866:            /**
867:             * Initializes this locale manager with the OpenCms system configuration.<p>
868:             * 
869:             * @param cms an OpenCms context object that must have been initialized with "Admin" permissions
870:             */
871:            public void initialize(CmsObject cms) {
872:
873:                // init the locale handler
874:                m_localeHandler.initHandler(cms);
875:                // set default locale 
876:                m_defaultLocale = (Locale) m_defaultLocales.get(0);
877:                // set initialized status
878:                m_initialized = true;
879:                if (CmsLog.INIT.isInfoEnabled()) {
880:                    CmsLog.INIT.info(Messages.get().getBundle().key(
881:                            Messages.INIT_I18N_CONFIG_VFSACCESS_0));
882:                }
883:            }
884:
885:            /**
886:             * Returns <code>true</code> if this locale manager is fully initialized.<p>
887:             *
888:             * This is required to prevent errors during unit tests,
889:             * simple unit tests will usually not have a fully
890:             * initialized locale manager available.<p>
891:             *
892:             * @return true if the locale manager is fully initialized
893:             */
894:            public boolean isInitialized() {
895:
896:                return m_initialized;
897:            }
898:
899:            /**
900:             * Sets the configured locale handler.<p>
901:             * 
902:             * @param localeHandler the locale handler to set
903:             */
904:            public void setLocaleHandler(I_CmsLocaleHandler localeHandler) {
905:
906:                if (localeHandler != null) {
907:                    m_localeHandler = localeHandler;
908:                }
909:                if (CmsLog.INIT.isInfoEnabled()) {
910:                    CmsLog.INIT.info(Messages.get().getBundle().key(
911:                            Messages.INIT_I18N_CONFIG_LOC_HANDLER_1,
912:                            m_localeHandler.getClass().getName()));
913:                }
914:            }
915:
916:            /**
917:             * Returns a list of available locale names derived from the given locale names.<p>
918:             * 
919:             * Each name in the given list is checked against the internal hash map of allowed locales, 
920:             * and is appended to the resulting list only if the locale exists.<p>
921:             * 
922:             * @param locales List of locales to check
923:             * @return list of available locales derived from the given locale names
924:             */
925:            private List checkLocaleNames(List locales) {
926:
927:                if (locales == null) {
928:                    return null;
929:                }
930:                List result = new ArrayList();
931:                Iterator i = locales.iterator();
932:                while (i.hasNext()) {
933:                    Locale locale = (Locale) i.next();
934:                    if (m_availableLocales.contains(locale)) {
935:                        result.add(locale);
936:                    }
937:                }
938:                return result;
939:            }
940:
941:            /**
942:             * Clears the caches in the locale manager.<p>
943:             */
944:            private void clearCaches() {
945:
946:                // flush all caches   
947:                OpenCms.getMemoryMonitor().flushLocales();
948:                CmsResourceBundleLoader.flushBundleCache();
949:
950:                if (LOG.isDebugEnabled()) {
951:                    LOG.debug(Messages.get().getBundle().key(
952:                            Messages.LOG_LOCALE_MANAGER_FLUSH_CACHE_1,
953:                            "EVENT_CLEAR_CACHES"));
954:                }
955:            }
956:
957:            /**
958:             * Internal helper, returns an array of default locales for the given default names.<p>
959:             *  
960:             * If required returns the system configured default locales.<p>
961:             * 
962:             * @param defaultNames the default locales to use, can be <code>null</code> or a comma separated list 
963:             *      of locales, for example <code>"en, de"</code>
964:             * 
965:             * @return an array of default locales for the given default names
966:             */
967:            private List getDefaultLocales(String defaultNames) {
968:
969:                List result = null;
970:                if (defaultNames != null) {
971:                    result = getAvailableLocales(defaultNames);
972:                }
973:                if ((result == null) || (result.size() == 0)) {
974:                    return getDefaultLocales();
975:                } else {
976:                    return result;
977:                }
978:            }
979:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.