1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.struts;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.LocaleUtil;
28  import com.liferay.portal.kernel.util.StringUtil;
29  
30  import java.io.InputStream;
31  
32  import java.net.URL;
33  
34  import java.util.Enumeration;
35  import java.util.Map;
36  import java.util.Properties;
37  import java.util.concurrent.locks.Lock;
38  import java.util.concurrent.locks.ReadWriteLock;
39  import java.util.concurrent.locks.ReentrantReadWriteLock;
40  
41  import javax.servlet.ServletContext;
42  
43  import org.apache.struts.util.MessageResourcesFactory;
44  import org.apache.struts.util.PropertyMessageResources;
45  
46  /**
47   * <a href="MultiMessageResources.java.html"><b><i>View Source</i></b></a>
48   *
49   * @author Brian Wing Shun Chan
50   * @author Bruno Farache
51   *
52   */
53  public class MultiMessageResources extends PropertyMessageResources {
54  
55      public MultiMessageResources(
56          MessageResourcesFactory factory, String config) {
57  
58          this(factory, config, true);
59      }
60  
61      public MultiMessageResources(
62          MessageResourcesFactory factory, String config, boolean returnNull) {
63  
64          super(factory, config, returnNull);
65  
66          _localeReadWriteLock = new ReentrantReadWriteLock();
67  
68          _localeReadLock = _localeReadWriteLock.readLock();
69          _localeWriteLock = _localeReadWriteLock.writeLock();
70  
71          _messagesReadWriteLock = new ReentrantReadWriteLock();
72  
73          _messagesReadLock = _messagesReadWriteLock.readLock();
74          _messagesWriteLock = _messagesReadWriteLock.writeLock();
75      }
76  
77      public Map<String, String> getMessages() {
78          _messagesReadLock.lock();
79  
80          try {
81              return messages;
82          }
83          finally {
84              _messagesReadLock.unlock();
85          }
86      }
87  
88      public void putLocale(String localeKey) {
89          _localeWriteLock.lock();
90  
91          try {
92              locales.put(localeKey, localeKey);
93          }
94          finally {
95              _localeWriteLock.unlock();
96          }
97      }
98  
99      public Properties putMessages(Properties props, String localeKey) {
100         Properties oldProps = new Properties();
101 
102         if (props.size() < 1) {
103             return oldProps;
104         }
105 
106         _messagesWriteLock.lock();
107 
108         try {
109             Enumeration<Object> names = props.keys();
110 
111             while (names.hasMoreElements()) {
112                 String key = (String)names.nextElement();
113 
114                 String message = getMessage(
115                     LocaleUtil.fromLanguageId(localeKey), key);
116 
117                 if (message != null) {
118                     oldProps.put(key, message);
119                 }
120 
121                 messages.put(
122                     messageKey(localeKey, key), props.getProperty(key));
123             }
124         }
125         finally {
126             _messagesWriteLock.unlock();
127         }
128 
129         return oldProps;
130     }
131 
132     public void setServletContext(ServletContext servletContext) {
133         _servletContext = servletContext;
134     }
135 
136     public void loadLocale(String localeKey) {
137         _localeReadLock.lock();
138 
139         try {
140             if (locales.containsKey(localeKey)) {
141                 return;
142             }
143         }
144         finally {
145             _localeReadLock.unlock();
146         }
147 
148         _localeWriteLock.lock();
149 
150         try {
151             if (locales.containsKey(localeKey)) {
152                 return;
153             }
154 
155             locales.put(localeKey, localeKey);
156         }
157         finally {
158             _localeWriteLock.unlock();
159         }
160 
161         String[] names = StringUtil.split(config.replace('.', '/'));
162 
163         for (int i = 0; i < names.length; i++) {
164             String name = names[i];
165 
166             if (localeKey.length() > 0) {
167                 name += "_" + localeKey;
168             }
169 
170             name += ".properties";
171 
172             _loadProps(name, localeKey, false);
173         }
174 
175         for (int i = 0; i < names.length; i++) {
176             String name = names[i];
177 
178             if (localeKey.length() > 0) {
179                 name += "_" + localeKey;
180             }
181 
182             name += ".properties";
183 
184             _loadProps(name, localeKey, true);
185         }
186     }
187 
188     private void _loadProps(
189         String name, String localeKey, boolean useServletContext) {
190 
191         Properties props = new Properties();
192 
193         try {
194             URL url = null;
195 
196             if (useServletContext) {
197                 url = _servletContext.getResource("/WEB-INF/" + name);
198             }
199             else {
200                 ClassLoader classLoader = getClass().getClassLoader();
201 
202                 url = classLoader.getResource(name);
203             }
204 
205             if (_log.isInfoEnabled()) {
206                 _log.info(
207                     "Attempting to load " + name + " " + localeKey + " " +
208                         useServletContext);
209             }
210 
211             if (url != null) {
212                 InputStream is = url.openStream();
213 
214                 props.load(is);
215 
216                 is.close();
217 
218                 if (_log.isInfoEnabled()) {
219                     _log.info(
220                         "Loading " + url + " with " + props.size() + " values");
221                 }
222             }
223         }
224         catch (Exception e) {
225             _log.warn(e);
226         }
227 
228         putMessages(props, localeKey);
229     }
230 
231     private static Log _log =
232          LogFactoryUtil.getLog(MultiMessageResources.class);
233 
234     private Lock _localeReadLock;
235     private ReadWriteLock _localeReadWriteLock;
236     private Lock _localeWriteLock;
237     private Lock _messagesReadLock;
238     private ReadWriteLock _messagesReadWriteLock;
239     private Lock _messagesWriteLock;
240     private transient ServletContext _servletContext;
241 
242 }