1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.localization.internal

File AbstractURLResourceTranslationBundle.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

8
37
5
1
185
90
15
0.41
7.4
5
3

Classes

Class Line # Actions
AbstractURLResourceTranslationBundle 47 37 0% 15 7
0.8686%
 

Contributing tests

This file is covered by 5 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.localization.internal;
21   
22    import java.io.FileNotFoundException;
23    import java.io.IOException;
24    import java.io.InputStream;
25    import java.net.MalformedURLException;
26    import java.net.URL;
27    import java.util.Locale;
28    import java.util.Map;
29    import java.util.Properties;
30   
31    import javax.inject.Inject;
32   
33    import org.slf4j.LoggerFactory;
34    import org.xwiki.component.manager.ComponentLookupException;
35    import org.xwiki.component.manager.ComponentManager;
36    import org.xwiki.localization.TranslationBundleContext;
37    import org.xwiki.localization.message.TranslationMessage;
38    import org.xwiki.localization.message.TranslationMessageParser;
39   
40    /**
41    * Base class for {@link org.xwiki.localization.TranslationBundle}s getting resource from classloader. Provides methods
42    * for loading properties from documents, watching loaded documents and invalidating cached translations.
43    *
44    * @version $Id: b54d193d22246db1c91c0c2ac5ec5331fad7317b $
45    * @since 4.5M1
46    */
 
47    public abstract class AbstractURLResourceTranslationBundle extends AbstractCachedTranslationBundle
48    {
49    /**
50    * The prefix to use in all resource based translations.
51    */
52    public static final String ID_PREFIX = "resource:";
53   
54    /**
55    * The file extension of files containing translations.
56    */
57    private static final String PROPERTIES_EXT = ".properties";
58   
59    /**
60    * Used to add no bundles to the list of current translation bundles.
61    */
62    @Inject
63    protected TranslationBundleContext bundleContext;
64   
65    /**
66    * Used to parse translation messages.
67    */
68    protected TranslationMessageParser translationMessageParser;
69   
70    /**
71    * The URL of the Locale.Root translations. Other Locale files will be "calculated" from it.
72    */
73    protected URL baseURL;
74   
75    /**
76    * @param baseURL the base URL from which to calculate all translations URLs
77    * @param componentManager used to lookup of the components
78    * @param translationMessageParser used to parse translation messages
79    * @throws ComponentLookupException failed to lookup some component
80    */
 
81  8 toggle public AbstractURLResourceTranslationBundle(URL baseURL, ComponentManager componentManager,
82    TranslationMessageParser translationMessageParser) throws ComponentLookupException
83    {
84  8 this.bundleContext = componentManager.getInstance(TranslationBundleContext.class);
85   
86  8 this.translationMessageParser = translationMessageParser;
87   
88  8 this.logger = LoggerFactory.getLogger(getClass());
89   
90  8 this.baseURL = baseURL;
91   
92  8 setId(ID_PREFIX + baseURL);
93    }
94   
95    /**
96    * @param locale the locale
97    * @return the URL corresponding to the passed {@link Locale}
98    */
 
99  17 toggle protected URL getLocaleURL(Locale locale)
100    {
101  17 String urlString = this.baseURL.toString();
102   
103  17 String localeURL = urlString;
104   
105  17 if (!locale.equals(Locale.ROOT)) {
106  10 if (urlString.endsWith(PROPERTIES_EXT)) {
107  10 int index = urlString.lastIndexOf('.');
108   
109  10 localeURL = urlString.substring(0, index);
110  10 localeURL += "_" + locale.toString();
111  10 localeURL += PROPERTIES_EXT;
112    } else {
113    // No idea what is it
114  0 return null;
115    }
116    }
117   
118  17 try {
119  17 return new URL(localeURL);
120    } catch (MalformedURLException e) {
121    // Should never happen
122  0 return null;
123    }
124    }
125   
126    /**
127    * @param locale the locale
128    * @return the {@link LocalizedTranslationBundle} corresponding to the passed {@link Locale}, null if none could be
129    * found
130    */
 
131  17 toggle protected LocalizedTranslationBundle loadResourceLocaleBundle(Locale locale)
132    {
133    // Find resource
134  17 URL localeURL = getLocaleURL(locale);
135   
136  17 if (localeURL == null) {
137  0 return LocalizedTranslationBundle.EMPTY;
138    }
139   
140    // Parse resource
141  17 Properties properties = new Properties();
142   
143  17 try (InputStream componentListStream = localeURL.openStream()) {
144  11 properties.load(componentListStream);
145    } catch (FileNotFoundException e) {
146    // No translation files for the passed locale
147  6 return LocalizedTranslationBundle.EMPTY;
148    } catch (IOException e) {
149  0 this.logger.error("Failed to parse resource [{}] as translation bundle", localeURL, e);
150    }
151   
152    // Convert to LocalBundle
153  11 DefaultLocalizedTranslationBundle localeBundle = new DefaultLocalizedTranslationBundle(this, locale);
154   
155  11 TranslationMessageParser parser = getTranslationMessageParser();
156   
157  11 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
158  11 if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
159  11 String key = (String) entry.getKey();
160  11 String message = (String) entry.getValue();
161   
162  11 TranslationMessage translationMessage = parser.parse(message);
163   
164  11 localeBundle.addTranslation(new DefaultTranslation(this.bundleContext, localeBundle, key,
165    translationMessage));
166    }
167    }
168   
169  11 return localeBundle;
170    }
171   
172    /**
173    * @return the parser to use
174    */
 
175  11 toggle protected TranslationMessageParser getTranslationMessageParser()
176    {
177  11 return this.translationMessageParser;
178    }
179   
 
180  17 toggle @Override
181    protected LocalizedTranslationBundle createBundle(Locale locale)
182    {
183  17 return loadResourceLocaleBundle(locale);
184    }
185    }