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 = null;
315
316 try {
317 session = portalPreferencesPersistence.openSession();
318
319 session.evict(preferences);
320
321 preferences = (com.liferay.portal.model.PortalPreferences)
322 session.get(
323 com.liferay.portal.model.impl.
324 PortalPreferencesImpl.class,
325 preferences.getPrimaryKey(), LockMode.UPGRADE);
326
327 PortalPreferencesImpl portalPreferencesImpl =
328 (PortalPreferencesImpl)
329 PortletPreferencesFactoryUtil.fromXML(
330 getOwnerId(), getOwnerType(),
331 preferences.getPreferences());
332
333 String originalXML = getOriginalXML();
334
335 if (originalXML.equals(preferences.getPreferences())) {
336 store();
337
338 return true;
339 }
340
341 if (!Arrays.equals(
342 originalValues,
343 portalPreferencesImpl.getValues(
344 key, (String[])null))) {
345
346 return false;
347 }
348
349 reset();
350
351 setOriginalPreferences(
352 portalPreferencesImpl.getOriginalPreferences());
353
354 setOriginalXML(preferences.getPreferences());
355
356 return null;
357 }
358 finally {
359 portalPreferencesPersistence.closeSession(session);
360 }
361 }
362
363 };
364 }
365
366 protected void validateStore(final Callable<?> callable, final String key)
367 throws Throwable {
368
369 while (true) {
370 String[] originalValues = super.getValues(key, null);
371
372 callable.call();
373
374 Boolean result = TransactionInvokerUtil.invoke(
375 TRANSACTION_ATTRIBUTE,
376 _createValidateCallable(originalValues, key));
377
378 if (result == null) {
379 continue;
380 }
381
382 if (!result) {
383 PortalPreferencesWrapperCacheUtil.remove(
384 getOwnerId(), getOwnerType());
385
386 throw new ConcurrentModificationException();
387 }
388
389 break;
390 }
391 }
392
393 @Override
394 public void store() throws IOException {
395 try {
396 PortalPreferencesLocalServiceUtil.updatePreferences(
397 getOwnerId(), getOwnerType(), this);
398 }
399 catch (SystemException se) {
400 throw new IOException(se.getMessage());
401 }
402 }
403
404 private String _encodeKey(String namespace, String key) {
405 if (Validator.isNull(namespace)) {
406 return key;
407 }
408 else {
409 return namespace.concat(StringPool.POUND).concat(key);
410 }
411 }
412
413 private static final String _RANDOM_KEY = "r";
414
415 private static Log _log = LogFactoryUtil.getLog(
416 PortalPreferencesImpl.class);
417
418 private boolean _signedIn;
419 private long _userId;
420
421 }