001
014
015 package com.liferay.portlet;
016
017 import com.liferay.portal.kernel.dao.orm.LockMode;
018 import com.liferay.portal.kernel.dao.orm.Session;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.transaction.TransactionAttribute;
024 import com.liferay.portal.kernel.transaction.TransactionInvokerUtil;
025 import com.liferay.portal.kernel.util.HashUtil;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.service.PortalPreferencesLocalServiceUtil;
029 import com.liferay.portal.service.persistence.PortalPreferencesPersistence;
030 import com.liferay.portal.service.persistence.PortalPreferencesUtil;
031
032 import java.io.IOException;
033 import java.io.Serializable;
034
035 import java.util.Arrays;
036 import java.util.Collections;
037 import java.util.ConcurrentModificationException;
038 import java.util.HashMap;
039 import java.util.Map;
040 import java.util.concurrent.Callable;
041
042 import javax.portlet.ReadOnlyException;
043
044
048 public class PortalPreferencesImpl
049 extends BasePreferencesImpl
050 implements Cloneable, PortalPreferences, Serializable {
051
052 public static final TransactionAttribute TRANSACTION_ATTRIBUTE;
053
054 static {
055 TransactionAttribute.Builder builder =
056 new TransactionAttribute.Builder();
057
058 builder.setRollbackForClasses(
059 PortalException.class, SystemException.class);
060
061 TRANSACTION_ATTRIBUTE = builder.build();
062 }
063
064 public PortalPreferencesImpl() {
065 this(0, 0, null, Collections.<String, Preference>emptyMap(), false);
066 }
067
068 public PortalPreferencesImpl(
069 long ownerId, int ownerType, String xml,
070 Map<String, Preference> preferences, boolean signedIn) {
071
072 super(ownerId, ownerType, xml, preferences);
073
074 _signedIn = signedIn;
075 }
076
077 @Override
078 public PortalPreferencesImpl clone() {
079 return new PortalPreferencesImpl(
080 getOwnerId(), getOwnerType(), getOriginalXML(),
081 new HashMap<String, Preference>(
082 getOriginalPreferences()), isSignedIn());
083 }
084
085 @Override
086 public boolean equals(Object obj) {
087 if (this == obj) {
088 return true;
089 }
090
091 if (!(obj instanceof PortalPreferencesImpl)) {
092 return false;
093 }
094
095 PortalPreferencesImpl portalPreferences = (PortalPreferencesImpl)obj;
096
097 if ((getOwnerId() == portalPreferences.getOwnerId()) &&
098 (getOwnerType() == portalPreferences.getOwnerType()) &&
099 getPreferences().equals(portalPreferences.getPreferences())) {
100
101 return true;
102 }
103 else {
104 return false;
105 }
106 }
107
108 @Override
109 public long getUserId() {
110 return _userId;
111 }
112
113 @Override
114 public String getValue(String namespace, String key) {
115 return getValue(namespace, key, null);
116 }
117
118 @Override
119 public String getValue(String namespace, String key, String defaultValue) {
120 key = _encodeKey(namespace, key);
121
122 return super.getValue(key, defaultValue);
123 }
124
125 @Override
126 public String[] getValues(String namespace, String key) {
127 return getValues(namespace, key, null);
128 }
129
130 @Override
131 public String[] getValues(
132 String namespace, String key, String[] defaultValue) {
133
134 key = _encodeKey(namespace, key);
135
136 return super.getValues(key, defaultValue);
137 }
138
139 @Override
140 public int hashCode() {
141 int hashCode = HashUtil.hash(0, getOwnerId());
142
143 hashCode = HashUtil.hash(hashCode, getOwnerType());
144 hashCode = HashUtil.hash(hashCode, getPreferences());
145
146 return hashCode;
147 }
148
149 @Override
150 public boolean isSignedIn() {
151 return _signedIn;
152 }
153
154 @Override
155 public void reset(final String key) throws ReadOnlyException {
156 if (isReadOnly(key)) {
157 throw new ReadOnlyException(key);
158 }
159
160 try {
161 validateStore(
162 new Callable<Void>() {
163
164 @Override
165 public Void call() {
166 Map<String, Preference> modifiedPreferences =
167 getModifiedPreferences();
168
169 modifiedPreferences.remove(key);
170
171 return null;
172 }
173
174 }, key);
175 }
176 catch (ConcurrentModificationException cme) {
177 throw cme;
178 }
179 catch (Throwable t) {
180 _log.error(t, t);
181 }
182 }
183
184 @Override
185 public void resetValues(String namespace) {
186 Map<String, Preference> preferences = getPreferences();
187
188 try {
189 for (Map.Entry<String, Preference> entry : preferences.entrySet()) {
190 String key = entry.getKey();
191
192 if (key.startsWith(namespace) && !isReadOnly(key)) {
193 reset(key);
194 }
195 }
196 }
197 catch (ConcurrentModificationException cme) {
198 throw cme;
199 }
200 catch (Exception e) {
201 _log.error(e, e);
202 }
203 }
204
205 @Override
206 public void setSignedIn(boolean signedIn) {
207 _signedIn = signedIn;
208 }
209
210 @Override
211 public void setUserId(long userId) {
212 _userId = userId;
213 }
214
215 @Override
216 public void setValue(
217 final String namespace, final String key, final String value) {
218
219 if (Validator.isNull(key) || key.equals(_RANDOM_KEY)) {
220 return;
221 }
222
223 try {
224 Callable<Void> callable = new Callable<Void>() {
225
226 @Override
227 public Void call() throws ReadOnlyException {
228 String encodedKey = _encodeKey(namespace, key);
229
230 if (value == null) {
231 reset(encodedKey);
232 }
233 else {
234 PortalPreferencesImpl.super.setValue(encodedKey, value);
235 }
236
237 return null;
238 }
239
240 };
241
242 if (_signedIn) {
243 validateStore(callable, _encodeKey(namespace, key));
244 }
245 else {
246 callable.call();
247 }
248 }
249 catch (ConcurrentModificationException cme) {
250 throw cme;
251 }
252 catch (Throwable t) {
253 _log.error(t, t);
254 }
255 }
256
257 @Override
258 public void setValues(
259 final String namespace, final String key, final String[] values) {
260
261 if (Validator.isNull(key) || key.equals(_RANDOM_KEY)) {
262 return;
263 }
264
265 try {
266 Callable<Void> callable = new Callable<Void>() {
267
268 @Override
269 public Void call() throws ReadOnlyException {
270 String encodedKey = _encodeKey(namespace, key);
271
272 if (values == null) {
273 reset(encodedKey);
274 }
275 else {
276 PortalPreferencesImpl.super.setValues(
277 encodedKey, values);
278 }
279
280 return null;
281 }
282
283 };
284
285 if (_signedIn) {
286 validateStore(callable, _encodeKey(namespace, key));
287 }
288 else {
289 callable.call();
290 }
291 }
292 catch (ConcurrentModificationException cme) {
293 throw cme;
294 }
295 catch (Throwable t) {
296 _log.error(t, t);
297 }
298 }
299
300 private Callable<Boolean> _createValidateCallable(
301 final String[] originalValues, final String key) {
302
303 return new Callable<Boolean>() {
304
305 @Override
306 public Boolean call() throws Exception {
307 com.liferay.portal.model.PortalPreferences
308 preferences = PortalPreferencesUtil.fetchByO_O(
309 getOwnerId(), getOwnerType(), false);
310
311 PortalPreferencesPersistence portalPreferencesPersistence =
312 PortalPreferencesUtil.getPersistence();
313
314 Session session =
315 portalPreferencesPersistence.getCurrentSession();
316
317 session.evict(preferences);
318
319 preferences = (com.liferay.portal.model.PortalPreferences)
320 session.get(
321 com.liferay.portal.model.impl.
322 PortalPreferencesImpl.class,
323 preferences.getPrimaryKey(), LockMode.UPGRADE);
324
325 PortalPreferencesImpl portalPreferencesImpl =
326 (PortalPreferencesImpl)
327 PortletPreferencesFactoryUtil.fromXML(
328 getOwnerId(), getOwnerType(),
329 preferences.getPreferences());
330
331 String originalXML = getOriginalXML();
332
333 if (originalXML.equals(preferences.getPreferences())) {
334 store();
335
336 return true;
337 }
338
339 if (!Arrays.equals(
340 originalValues,
341 portalPreferencesImpl.getValues(key, (String[])null))) {
342
343 return false;
344 }
345
346 reset();
347
348 setOriginalPreferences(
349 portalPreferencesImpl.getOriginalPreferences());
350
351 setOriginalXML(preferences.getPreferences());
352
353 return null;
354 }
355
356 };
357 }
358
359 protected void validateStore(final Callable<?> callable, final String key)
360 throws Throwable {
361
362 while (true) {
363 String[] originalValues = super.getValues(key, null);
364
365 callable.call();
366
367 Boolean result = TransactionInvokerUtil.invoke(
368 TRANSACTION_ATTRIBUTE,
369 _createValidateCallable(originalValues, key));
370
371 if (result == null) {
372 continue;
373 }
374
375 if (!result) {
376 PortalPreferencesWrapperCacheUtil.remove(
377 getOwnerId(), getOwnerType());
378
379 throw new ConcurrentModificationException();
380 }
381
382 break;
383 }
384 }
385
386 @Override
387 public void store() throws IOException {
388 try {
389 PortalPreferencesLocalServiceUtil.updatePreferences(
390 getOwnerId(), getOwnerType(), this);
391 }
392 catch (SystemException se) {
393 throw new IOException(se.getMessage());
394 }
395 }
396
397 private String _encodeKey(String namespace, String key) {
398 if (Validator.isNull(namespace)) {
399 return key;
400 }
401 else {
402 return namespace.concat(StringPool.POUND).concat(key);
403 }
404 }
405
406 private static final String _RANDOM_KEY = "r";
407
408 private static Log _log = LogFactoryUtil.getLog(
409 PortalPreferencesImpl.class);
410
411 private boolean _signedIn;
412 private long _userId;
413
414 }