1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portlet;
21  
22  import com.liferay.portal.SystemException;
23  import com.liferay.portal.kernel.log.Log;
24  import com.liferay.portal.kernel.log.LogFactoryUtil;
25  import com.liferay.portal.model.Portlet;
26  import com.liferay.portal.service.PortletLocalServiceUtil;
27  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
28  import com.liferay.portal.util.PortalUtil;
29  import com.liferay.portal.util.PortletKeys;
30  import com.liferay.util.xml.XMLFormatter;
31  
32  import java.io.IOException;
33  import java.io.Serializable;
34  
35  import java.util.Collections;
36  import java.util.Enumeration;
37  import java.util.HashMap;
38  import java.util.Map;
39  
40  import javax.portlet.PortletPreferences;
41  import javax.portlet.PreferencesValidator;
42  import javax.portlet.ReadOnlyException;
43  import javax.portlet.ValidatorException;
44  
45  /**
46   * <a href="PortletPreferencesImpl.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Brian Wing Shun Chan
49   *
50   */
51  public class PortletPreferencesImpl
52      implements Cloneable, PortletPreferences, Serializable {
53  
54      public PortletPreferencesImpl() {
55          this(0, 0, 0, 0, null, new HashMap<String, Preference>());
56      }
57  
58      public PortletPreferencesImpl(
59          long companyId, long ownerId, int ownerType, long plid,
60          String portletId, Map<String, Preference> preferences) {
61  
62          _companyId = companyId;
63          _ownerId = ownerId;
64          _ownerType = ownerType;
65          _plid = plid;
66          _portletId = portletId;
67          _preferences = preferences;
68      }
69  
70      public Map<String, String[]> getMap() {
71          Map<String, String[]> map = new HashMap<String, String[]>();
72  
73          for (Map.Entry<String, Preference> entry : _preferences.entrySet()) {
74              String key = entry.getKey();
75              Preference preference = entry.getValue();
76  
77              map.put(key, _getActualValues(preference.getValues()));
78          }
79  
80          return Collections.unmodifiableMap(map);
81      }
82  
83      public Enumeration<String> getNames() {
84          return Collections.enumeration(_preferences.keySet());
85      }
86  
87      public String getValue(String key, String def) {
88          if (key == null) {
89              throw new IllegalArgumentException();
90          }
91  
92          Preference preference = _preferences.get(key);
93  
94          String[] values = null;
95  
96          if (preference != null) {
97              values = preference.getValues();
98          }
99  
100         if ((values != null) && (values.length > 0)) {
101             return _getActualValue(values[0]);
102         }
103         else {
104             return _getActualValue(def);
105         }
106     }
107 
108     public void setValue(String key, String value) throws ReadOnlyException {
109         if (key == null) {
110             throw new IllegalArgumentException();
111         }
112 
113         value = _getXmlSafeValue(value);
114 
115         Preference preference = _preferences.get(key);
116 
117         if (preference == null) {
118             preference = new Preference(key, value);
119 
120             _preferences.put(key, preference);
121         }
122 
123         if (preference.isReadOnly()) {
124             throw new ReadOnlyException(key);
125         }
126         else {
127             preference.setValues(new String[] {value});
128         }
129     }
130 
131     public String[] getValues(String key, String[] def) {
132         if (key == null) {
133             throw new IllegalArgumentException();
134         }
135 
136         Preference preference = _preferences.get(key);
137 
138         String[] values = null;
139         if (preference != null) {
140             values = preference.getValues();
141         }
142 
143         if ((values != null) && (values.length > 0)) {
144             return _getActualValues(values);
145         }
146         else {
147             return _getActualValues(def);
148         }
149     }
150 
151     public void setValues(String key, String[] values)
152         throws ReadOnlyException {
153 
154         if (key == null) {
155             throw new IllegalArgumentException();
156         }
157 
158         values = _getXmlSafeValues(values);
159 
160         Preference preference = _preferences.get(key);
161 
162         if (preference == null) {
163             preference = new Preference(key, values);
164 
165             _preferences.put(key, preference);
166         }
167 
168         if (preference.isReadOnly()) {
169             throw new ReadOnlyException(key);
170         }
171         else {
172             preference.setValues(values);
173         }
174     }
175 
176     public boolean isReadOnly(String key) {
177         if (key == null) {
178             throw new IllegalArgumentException();
179         }
180 
181         Preference preference = _preferences.get(key);
182 
183         if (preference != null && preference.isReadOnly()) {
184             return true;
185         }
186         else {
187             return false;
188         }
189     }
190 
191     public void reset() {
192         _preferences.clear();
193     }
194 
195     public void reset(String key) throws ReadOnlyException {
196         if (isReadOnly(key)) {
197             throw new ReadOnlyException(key);
198         }
199 
200         if (_defaultPreferences == null) {
201             try {
202                 if ((_portletId != null) &&
203                     (!_portletId.equals(PortletKeys.LIFERAY_PORTAL))) {
204 
205                     _defaultPreferences = PortletPreferencesLocalServiceUtil.
206                         getDefaultPreferences(_companyId, _portletId);
207                 }
208             }
209             catch (Exception e) {
210                 _log.error(e, e);
211             }
212         }
213 
214         String[] defaultValues = null;
215 
216         if (_defaultPreferences != null) {
217             defaultValues = _defaultPreferences.getValues(key, defaultValues);
218         }
219 
220         if (defaultValues != null) {
221             setValues(key, defaultValues);
222         }
223         else {
224             _preferences.remove(key);
225         }
226     }
227 
228     public void store() throws IOException, ValidatorException {
229         if (_portletId == null) {
230             throw new UnsupportedOperationException();
231         }
232 
233         try {
234             Portlet portlet = PortletLocalServiceUtil.getPortletById(
235                 _companyId, _portletId);
236 
237             if (!_portletId.equals(PortletKeys.LIFERAY_PORTAL)) {
238                 PreferencesValidator preferencesValidator =
239                     PortalUtil.getPreferencesValidator(portlet);
240 
241                 if (preferencesValidator != null) {
242                     preferencesValidator.validate(this);
243                 }
244             }
245 
246             PortletPreferencesLocalServiceUtil.updatePreferences(
247                 _ownerId, _ownerType, _plid, _portletId, this);
248         }
249         catch (SystemException se) {
250             throw new IOException(se.getMessage());
251         }
252     }
253 
254     public Object clone() {
255         Map<String, Preference> preferencesClone =
256             new HashMap<String, Preference>();
257 
258         for (Map.Entry<String, Preference> entry : _preferences.entrySet()) {
259             String key = entry.getKey();
260             Preference preference = entry.getValue();
261 
262             preferencesClone.put(key, (Preference)preference.clone());
263         }
264 
265         return new PortletPreferencesImpl(
266             _companyId, _ownerId, _ownerType, _plid, _portletId,
267             preferencesClone);
268     }
269 
270     public boolean equals(Object obj) {
271         PortletPreferencesImpl portletPreferences = (PortletPreferencesImpl)obj;
272 
273         if (this == portletPreferences) {
274             return true;
275         }
276 
277         if ((getCompanyId() == portletPreferences.getCompanyId()) &&
278             (getOwnerId() == portletPreferences.getOwnerId()) &&
279             (getOwnerType() == portletPreferences.getOwnerType()) &&
280             (getPlid() == portletPreferences.getPlid()) &&
281             (getPortletId().equals(portletPreferences.getPortletId())) &&
282             (getMap().equals(portletPreferences.getMap()))) {
283 
284             return true;
285         }
286         else {
287             return false;
288         }
289     }
290 
291     protected long getCompanyId() {
292         return  _companyId;
293     }
294 
295     protected long getOwnerId() {
296         return _ownerId;
297     }
298 
299     protected int getOwnerType() {
300         return _ownerType;
301     }
302 
303     protected long getPlid() {
304         return _plid;
305     }
306 
307     protected String getPortletId() {
308         return _portletId;
309     }
310 
311     protected Map<String, Preference> getPreferences() {
312         return _preferences;
313     }
314 
315     private String _getActualValue(String value) {
316         if ((value == null) || (value.equals(_NULL_VALUE))) {
317             return null;
318         }
319         else {
320             return XMLFormatter.fromCompactSafe(value);
321         }
322     }
323 
324     private String[] _getActualValues(String[] values) {
325         if (values == null) {
326             return null;
327         }
328 
329         if ((values.length == 1) && (_getActualValue(values[0]) == null)) {
330             return null;
331         }
332 
333         String[] actualValues = new String[values.length];
334 
335         System.arraycopy(values, 0, actualValues, 0, values.length);
336 
337         for (int i = 0; i < actualValues.length; i++) {
338             actualValues[i] = _getActualValue(actualValues[i]);
339         }
340 
341         return actualValues;
342     }
343 
344     private String _getXmlSafeValue(String value) {
345         if (value == null) {
346             return _NULL_VALUE;
347         }
348         else {
349             return XMLFormatter.toCompactSafe(value);
350         }
351     }
352 
353     private String[] _getXmlSafeValues(String[] values) {
354         if (values == null) {
355             return new String[] {
356                     _getXmlSafeValue(null)
357                 };
358         }
359 
360         String[] xmlSafeValues = new String[values.length];
361 
362         System.arraycopy(values, 0, xmlSafeValues, 0, values.length);
363 
364         for (int i = 0; i < xmlSafeValues.length; i++) {
365             if (xmlSafeValues[i] == null) {
366                 xmlSafeValues[i] = _getXmlSafeValue(xmlSafeValues[i]);
367             }
368         }
369 
370         return xmlSafeValues;
371     }
372 
373     private static final String _NULL_VALUE = "NULL_VALUE";
374 
375     private static Log _log =
376         LogFactoryUtil.getLog(PortletPreferencesImpl.class);
377 
378     private long _companyId;
379     private long _ownerId;
380     private int _ownerType;
381     private long _plid;
382     private String _portletId;
383     private Map<String, Preference> _preferences;
384     private PortletPreferences _defaultPreferences;
385 
386 }