001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.HashCode;
021    import com.liferay.portal.kernel.util.HashCodeFactoryUtil;
022    import com.liferay.portal.model.Portlet;
023    import com.liferay.portal.service.PortletLocalServiceUtil;
024    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
025    import com.liferay.portal.util.PortalUtil;
026    import com.liferay.portal.util.PortletKeys;
027    import com.liferay.util.xml.XMLFormatter;
028    
029    import java.io.IOException;
030    import java.io.Serializable;
031    
032    import java.util.Collections;
033    import java.util.Enumeration;
034    import java.util.HashMap;
035    import java.util.Map;
036    
037    import javax.portlet.PortletPreferences;
038    import javax.portlet.PreferencesValidator;
039    import javax.portlet.ReadOnlyException;
040    import javax.portlet.ValidatorException;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     */
045    public class PortletPreferencesImpl
046            implements Cloneable, PortletPreferences, Serializable {
047    
048            public PortletPreferencesImpl() {
049                    this(0, 0, 0, 0, null, new HashMap<String, Preference>());
050            }
051    
052            public PortletPreferencesImpl(
053                    long companyId, long ownerId, int ownerType, long plid,
054                    String portletId, Map<String, Preference> preferences) {
055    
056                    _companyId = companyId;
057                    _ownerId = ownerId;
058                    _ownerType = ownerType;
059                    _plid = plid;
060                    _portletId = portletId;
061                    _originalPreferences = preferences;
062            }
063    
064            public Object clone() {
065                    return new PortletPreferencesImpl(
066                            _companyId, _ownerId, _ownerType, _plid, _portletId,
067                            _originalPreferences);
068            }
069    
070            public boolean equals(Object obj) {
071                    PortletPreferencesImpl portletPreferences = (PortletPreferencesImpl)obj;
072    
073                    if (this == portletPreferences) {
074                            return true;
075                    }
076    
077                    if ((getCompanyId() == portletPreferences.getCompanyId()) &&
078                            (getOwnerId() == portletPreferences.getOwnerId()) &&
079                            (getOwnerType() == portletPreferences.getOwnerType()) &&
080                            (getPlid() == portletPreferences.getPlid()) &&
081                            (getPortletId().equals(portletPreferences.getPortletId())) &&
082                            (getMap().equals(portletPreferences.getMap()))) {
083    
084                            return true;
085                    }
086                    else {
087                            return false;
088                    }
089            }
090    
091            public Map<String, String[]> getMap() {
092                    Map<String, String[]> map = new HashMap<String, String[]>();
093    
094                    for (Map.Entry<String, Preference> entry :
095                                    getPreferences().entrySet()) {
096    
097                            String key = entry.getKey();
098                            Preference preference = entry.getValue();
099    
100                            map.put(key, _getActualValues(preference.getValues()));
101                    }
102    
103                    return Collections.unmodifiableMap(map);
104            }
105    
106            public Enumeration<String> getNames() {
107                    return Collections.enumeration(getPreferences().keySet());
108            }
109    
110            public String getValue(String key, String def) {
111                    if (key == null) {
112                            throw new IllegalArgumentException();
113                    }
114    
115                    Preference preference = getPreferences().get(key);
116    
117                    String[] values = null;
118    
119                    if (preference != null) {
120                            values = preference.getValues();
121                    }
122    
123                    if ((values != null) && (values.length > 0)) {
124                            return _getActualValue(values[0]);
125                    }
126                    else {
127                            return _getActualValue(def);
128                    }
129            }
130    
131            public String[] getValues(String key, String[] def) {
132                    if (key == null) {
133                            throw new IllegalArgumentException();
134                    }
135    
136                    Preference preference = getPreferences().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 int hashCode() {
152                    HashCode hashCode = HashCodeFactoryUtil.getHashCode();
153    
154                    hashCode.append(_companyId);
155                    hashCode.append(_ownerId);
156                    hashCode.append(_ownerType);
157                    hashCode.append(_plid);
158                    hashCode.append(_portletId);
159                    hashCode.append(getPreferences());
160    
161                    return hashCode.toHashCode();
162            }
163    
164            public boolean isReadOnly(String key) {
165                    if (key == null) {
166                            throw new IllegalArgumentException();
167                    }
168    
169                    Preference preference = getPreferences().get(key);
170    
171                    if ((preference != null) && preference.isReadOnly()) {
172                            return true;
173                    }
174                    else {
175                            return false;
176                    }
177            }
178    
179            public void reset() {
180                    _getModifiedPreferences().clear();
181            }
182    
183            public void reset(String key) throws ReadOnlyException {
184                    if (isReadOnly(key)) {
185                            throw new ReadOnlyException(key);
186                    }
187    
188                    if (_defaultPreferences == null) {
189                            try {
190                                    if ((_portletId != null) &&
191                                            (!_portletId.equals(PortletKeys.LIFERAY_PORTAL))) {
192    
193                                            _defaultPreferences = PortletPreferencesLocalServiceUtil.
194                                                    getDefaultPreferences(_companyId, _portletId);
195                                    }
196                            }
197                            catch (Exception e) {
198                                    if (_log.isWarnEnabled()) {
199                                            _log.warn(e, e);
200                                    }
201                            }
202                    }
203    
204                    String[] defaultValues = null;
205    
206                    if (_defaultPreferences != null) {
207                            defaultValues = _defaultPreferences.getValues(key, defaultValues);
208                    }
209    
210                    if (defaultValues != null) {
211                            setValues(key, defaultValues);
212                    }
213                    else {
214                            _getModifiedPreferences().remove(key);
215                    }
216            }
217    
218            public void setValue(String key, String value) throws ReadOnlyException {
219                    if (key == null) {
220                            throw new IllegalArgumentException();
221                    }
222    
223                    value = _getXmlSafeValue(value);
224    
225                    Preference preference = _getModifiedPreferences().get(key);
226    
227                    if (preference == null) {
228                            preference = new Preference(key, value);
229    
230                            _getModifiedPreferences().put(key, preference);
231                    }
232    
233                    if (preference.isReadOnly()) {
234                            throw new ReadOnlyException(key);
235                    }
236                    else {
237                            preference.setValues(new String[] {value});
238                    }
239            }
240    
241            public void setValues(String key, String[] values)
242                    throws ReadOnlyException {
243    
244                    if (key == null) {
245                            throw new IllegalArgumentException();
246                    }
247    
248                    values = _getXmlSafeValues(values);
249    
250                    Preference preference = _getModifiedPreferences().get(key);
251    
252                    if (preference == null) {
253                            preference = new Preference(key, values);
254    
255                            _getModifiedPreferences().put(key, preference);
256                    }
257    
258                    if (preference.isReadOnly()) {
259                            throw new ReadOnlyException(key);
260                    }
261                    else {
262                            preference.setValues(values);
263                    }
264            }
265    
266            public void store() throws IOException, ValidatorException {
267                    if (_portletId == null) {
268                            throw new UnsupportedOperationException();
269                    }
270    
271                    try {
272                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
273                                    _companyId, _portletId);
274    
275                            if (!_portletId.equals(PortletKeys.LIFERAY_PORTAL)) {
276                                    PreferencesValidator preferencesValidator =
277                                            PortalUtil.getPreferencesValidator(portlet);
278    
279                                    if (preferencesValidator != null) {
280                                            preferencesValidator.validate(this);
281                                    }
282                            }
283    
284                            PortletPreferencesLocalServiceUtil.updatePreferences(
285                                    _ownerId, _ownerType, _plid, _portletId, this);
286                    }
287                    catch (SystemException se) {
288                            throw new IOException(se.getMessage());
289                    }
290            }
291    
292            protected long getCompanyId() {
293                    return  _companyId;
294            }
295    
296            protected long getOwnerId() {
297                    return _ownerId;
298            }
299    
300            protected int getOwnerType() {
301                    return _ownerType;
302            }
303    
304            protected long getPlid() {
305                    return _plid;
306            }
307    
308            protected String getPortletId() {
309                    return _portletId;
310            }
311    
312            protected Map<String, Preference> getPreferences() {
313                    if (_modifiedPreferences == null) {
314                            return _originalPreferences;
315                    }
316                    else {
317                            return _modifiedPreferences;
318                    }
319            }
320    
321            private String _getActualValue(String value) {
322                    if ((value == null) || (value.equals(_NULL_VALUE))) {
323                            return null;
324                    }
325                    else {
326                            return XMLFormatter.fromCompactSafe(value);
327                    }
328            }
329    
330            private String[] _getActualValues(String[] values) {
331                    if (values == null) {
332                            return null;
333                    }
334    
335                    if ((values.length == 1) && (_getActualValue(values[0]) == null)) {
336                            return null;
337                    }
338    
339                    String[] actualValues = new String[values.length];
340    
341                    System.arraycopy(values, 0, actualValues, 0, values.length);
342    
343                    for (int i = 0; i < actualValues.length; i++) {
344                            actualValues[i] = _getActualValue(actualValues[i]);
345                    }
346    
347                    return actualValues;
348            }
349    
350            private Map<String, Preference> _getModifiedPreferences() {
351                    if (_modifiedPreferences == null) {
352                            _modifiedPreferences = new HashMap<String, Preference>();
353    
354                            for (Map.Entry<String, Preference> entry :
355                                            _originalPreferences.entrySet()) {
356    
357                                    String key = entry.getKey();
358                                    Preference preference = entry.getValue();
359    
360                                    _modifiedPreferences.put(key, (Preference)preference.clone());
361                            }
362                    }
363    
364                    return _modifiedPreferences;
365            }
366    
367            private String _getXmlSafeValue(String value) {
368                    if (value == null) {
369                            return _NULL_VALUE;
370                    }
371                    else {
372                            return XMLFormatter.toCompactSafe(value);
373                    }
374            }
375    
376            private String[] _getXmlSafeValues(String[] values) {
377                    if (values == null) {
378                            return new String[] {
379                                            _getXmlSafeValue(null)
380                                    };
381                    }
382    
383                    String[] xmlSafeValues = new String[values.length];
384    
385                    System.arraycopy(values, 0, xmlSafeValues, 0, values.length);
386    
387                    for (int i = 0; i < xmlSafeValues.length; i++) {
388                            if (xmlSafeValues[i] == null) {
389                                    xmlSafeValues[i] = _getXmlSafeValue(xmlSafeValues[i]);
390                            }
391                    }
392    
393                    return xmlSafeValues;
394            }
395    
396            private static final String _NULL_VALUE = "NULL_VALUE";
397    
398            private static Log _log = LogFactoryUtil.getLog(
399                    PortletPreferencesImpl.class);
400    
401            private long _companyId;
402            private PortletPreferences _defaultPreferences;
403            private Map<String, Preference> _modifiedPreferences;
404            private Map<String, Preference> _originalPreferences;
405            private long _ownerId;
406            private int _ownerType;
407            private long _plid;
408            private String _portletId;
409    
410    }