001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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, Collections.EMPTY_MAP);
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                            if (_originalPreferences == Collections.EMPTY_MAP) {
315                                    _originalPreferences = new HashMap<String, Preference>();
316                            }
317    
318                            return _originalPreferences;
319                    }
320                    else {
321                            return _modifiedPreferences;
322                    }
323            }
324    
325            private String _getActualValue(String value) {
326                    if ((value == null) || (value.equals(_NULL_VALUE))) {
327                            return null;
328                    }
329                    else {
330                            return XMLFormatter.fromCompactSafe(value);
331                    }
332            }
333    
334            private String[] _getActualValues(String[] values) {
335                    if (values == null) {
336                            return null;
337                    }
338    
339                    if ((values.length == 1) && (_getActualValue(values[0]) == null)) {
340                            return null;
341                    }
342    
343                    String[] actualValues = new String[values.length];
344    
345                    System.arraycopy(values, 0, actualValues, 0, values.length);
346    
347                    for (int i = 0; i < actualValues.length; i++) {
348                            actualValues[i] = _getActualValue(actualValues[i]);
349                    }
350    
351                    return actualValues;
352            }
353    
354            private Map<String, Preference> _getModifiedPreferences() {
355                    if (_modifiedPreferences == null) {
356                            _modifiedPreferences = new HashMap<String, Preference>();
357    
358                            for (Map.Entry<String, Preference> entry :
359                                            _originalPreferences.entrySet()) {
360    
361                                    String key = entry.getKey();
362                                    Preference preference = entry.getValue();
363    
364                                    _modifiedPreferences.put(key, (Preference)preference.clone());
365                            }
366                    }
367    
368                    return _modifiedPreferences;
369            }
370    
371            private String _getXmlSafeValue(String value) {
372                    if (value == null) {
373                            return _NULL_VALUE;
374                    }
375                    else {
376                            return XMLFormatter.toCompactSafe(value);
377                    }
378            }
379    
380            private String[] _getXmlSafeValues(String[] values) {
381                    if (values == null) {
382                            return new String[] {_getXmlSafeValue(null)};
383                    }
384    
385                    String[] xmlSafeValues = new String[values.length];
386    
387                    System.arraycopy(values, 0, xmlSafeValues, 0, values.length);
388    
389                    for (int i = 0; i < xmlSafeValues.length; i++) {
390                            if (xmlSafeValues[i] == null) {
391                                    xmlSafeValues[i] = _getXmlSafeValue(xmlSafeValues[i]);
392                            }
393                    }
394    
395                    return xmlSafeValues;
396            }
397    
398            private static final String _NULL_VALUE = "NULL_VALUE";
399    
400            private static Log _log = LogFactoryUtil.getLog(
401                    PortletPreferencesImpl.class);
402    
403            private long _companyId;
404            private PortletPreferences _defaultPreferences;
405            private Map<String, Preference> _modifiedPreferences;
406            private Map<String, Preference> _originalPreferences;
407            private long _ownerId;
408            private int _ownerType;
409            private long _plid;
410            private String _portletId;
411    
412    }