001    package org.apache.turbine.services.localization;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.Locale;
023    import java.util.MissingResourceException;
024    
025    import org.apache.commons.logging.Log;
026    import org.apache.commons.logging.LogFactory;
027    import org.apache.fulcrum.localization.LocalizationService;
028    import org.apache.turbine.services.InstantiationException;
029    import org.apache.turbine.services.TurbineServices;
030    import org.apache.turbine.services.pull.ApplicationTool;
031    import org.apache.turbine.util.RunData;
032    /**
033     * A pull tool which provides lookups for localized text by delegating
034     * to the configured Fulcrum <code>LocalizationService</code>.
035     *
036     * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
037     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
038     * @author <a href="mailto:jon@collab.net">Jon Stevens</a>
039     */
040    public class LocalizationTool implements ApplicationTool
041    {
042        /** Logging */
043        private static Log log = LogFactory.getLog(LocalizationTool.class);
044        /** Fulcrum Localization component */
045        private LocalizationService localizationService;
046        /**
047         * The language and country information parsed from the request's
048         * <code>Accept-Language</code> header.  Reset on each request.
049         */
050        protected Locale locale;
051    
052        /**
053         * Lazy load the LocalizationService.
054         * @return a fulcrum LocalizationService
055         */
056        public LocalizationService getLocalizationService()
057        {
058            if (localizationService == null)
059            {
060                try
061                {
062                    localizationService = (LocalizationService)TurbineServices.getInstance()
063                        .getService(LocalizationService.ROLE);
064                }
065                catch (Exception e)
066                {
067                    throw new InstantiationException("Problem looking up Localization Service:"+e.getMessage());
068                }
069            }
070            return localizationService;
071        }
072    
073        /**
074         * Creates a new instance.  Used by <code>PullService</code>.
075         */
076        public LocalizationTool()
077        {
078            refresh();
079        }
080    
081        /**
082         * <p>Performs text lookups for localization.</p>
083         *
084         * <p>Assuming there is a instance of this class with a HTTP
085         * request set in your template's context named <code>l10n</code>,
086         * the VTL <code>$l10n.HELLO</code> would render to
087         * <code>hello</code> for English requests and <code>hola</code>
088         * in Spanish (depending on the value of the HTTP request's
089         * <code>Accept-Language</code> header).</p>
090         *
091         * @param key The identifier for the localized text to retrieve.
092         * @return The localized text.
093         */
094        public String get(String key)
095        {
096            try
097            {
098                return getLocalizationService().getString(getBundleName(null), getLocale(), key);
099            }
100            catch (MissingResourceException noKey)
101            {
102                log.error(noKey);
103                return null;
104            }
105        }
106    
107        /**
108         * Gets the current locale.
109         *
110         * @return The locale currently in use.
111         */
112        public Locale getLocale()
113        {
114            return locale;
115        }
116    
117        /**
118         * The return value of this method is used to set the name of the
119         * bundle used by this tool.  Useful as a hook for using a
120         * different bundle than specified in your
121         * <code>LocalizationService</code> configuration.
122         *
123         * @param data The inputs passed from {@link #init(Object)}.
124         * (ignored by this implementation).
125         */
126        protected String getBundleName(Object data)
127        {
128            return getLocalizationService().getDefaultBundleName();
129        }
130    
131        /**
132         * Formats a localized value using the provided object.
133         *
134         * @param key The identifier for the localized text to retrieve,
135         * @param arg1 The object to use as {0} when formatting the localized text.
136         * @return Formatted localized text.
137         * @see #format(String, Locale, String, Object[])
138         */
139        public String format(String key, Object arg1)
140        {
141            return getLocalizationService()
142                    .format(getBundleName(null), getLocale(), key, arg1);
143        }
144    
145        /**
146         * Formats a localized value using the provided objects.
147         *
148         * @param key The identifier for the localized text to retrieve,
149         * @param arg1 The object to use as {0} when formatting the localized text.
150         * @param arg2 The object to use as {1} when formatting the localized text.
151         * @return Formatted localized text.
152         * @see #format(String, Locale, String, Object[])
153         */
154        public String format(String key, Object arg1, Object arg2)
155        {
156            return getLocalizationService()
157                    .format(getBundleName(null), getLocale(), key, arg1, arg2);
158        }
159    
160        /**
161         * Formats a localized value using the provided objects.
162         *
163         * @param key The identifier for the localized text to retrieve,
164         * @param args The objects to use as {0}, {1}, etc. when
165         *             formatting the localized text.
166         * @return Formatted localized text.
167         */
168        public String format(String key, Object[] args)
169        {
170            return getLocalizationService()
171                    .format(getBundleName(null), getLocale(), key, args);
172        }
173    
174        // ApplicationTool implementation
175    
176        /**
177         * Sets the request to get the <code>Accept-Language</code> header
178         * from (reset on each request).
179         */
180        public void init(Object data)
181        {
182            if (data instanceof RunData)
183            {
184                // Pull necessary information out of RunData while we have
185                // a reference to it.
186                locale = getLocalizationService().getLocale(((RunData) data).getRequest());
187            }
188        }
189    
190        /**
191         * No-op.
192         */
193        public void refresh()
194        {
195            locale = null;
196        }
197    }