001    /**
002     * Copyright (c) 2000-2013 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.cache.PortalCache;
018    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
022    import com.liferay.portal.kernel.portlet.LiferayPortletMode;
023    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.JavaConstants;
026    import com.liferay.portal.kernel.util.ParamUtil;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.model.Group;
030    import com.liferay.portal.model.Layout;
031    import com.liferay.portal.model.LayoutConstants;
032    import com.liferay.portal.model.LayoutTypePortlet;
033    import com.liferay.portal.model.Portlet;
034    import com.liferay.portal.model.PortletConstants;
035    import com.liferay.portal.model.PortletPreferencesIds;
036    import com.liferay.portal.security.auth.PrincipalException;
037    import com.liferay.portal.security.permission.ActionKeys;
038    import com.liferay.portal.security.permission.PermissionChecker;
039    import com.liferay.portal.security.permission.PermissionThreadLocal;
040    import com.liferay.portal.service.GroupLocalServiceUtil;
041    import com.liferay.portal.service.PortalPreferencesLocalServiceUtil;
042    import com.liferay.portal.service.PortletLocalServiceUtil;
043    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
044    import com.liferay.portal.service.UserLocalServiceUtil;
045    import com.liferay.portal.service.permission.LayoutPermissionUtil;
046    import com.liferay.portal.theme.ThemeDisplay;
047    import com.liferay.portal.util.PortalUtil;
048    import com.liferay.portal.util.PortletKeys;
049    import com.liferay.portal.util.WebKeys;
050    import com.liferay.portal.xml.StAXReaderUtil;
051    import com.liferay.portlet.portletconfiguration.util.ConfigurationPortletRequest;
052    
053    import java.util.ArrayList;
054    import java.util.Collections;
055    import java.util.HashMap;
056    import java.util.List;
057    import java.util.Map;
058    
059    import javax.portlet.PortletPreferences;
060    import javax.portlet.PortletRequest;
061    import javax.portlet.PreferencesValidator;
062    import javax.portlet.filter.PortletRequestWrapper;
063    
064    import javax.servlet.http.HttpServletRequest;
065    import javax.servlet.http.HttpSession;
066    
067    import javax.xml.stream.XMLEventReader;
068    import javax.xml.stream.XMLInputFactory;
069    import javax.xml.stream.XMLStreamException;
070    import javax.xml.stream.events.EndElement;
071    import javax.xml.stream.events.StartElement;
072    import javax.xml.stream.events.XMLEvent;
073    
074    /**
075     * @author Brian Wing Shun Chan
076     * @author Alexander Chow
077     * @author Minhchau Dang
078     * @author Raymond Aug??
079     */
080    @DoPrivileged
081    public class PortletPreferencesFactoryImpl
082            implements PortletPreferencesFactory {
083    
084            @Override
085            public PortletPreferences fromDefaultXML(String xml)
086                    throws SystemException {
087    
088                    Map<String, Preference> preferencesMap = toPreferencesMap(xml);
089    
090                    return new PortletPreferencesImpl(xml, preferencesMap);
091            }
092    
093            @Override
094            public PortalPreferencesImpl fromXML(
095                            long ownerId, int ownerType, String xml)
096                    throws SystemException {
097    
098                    try {
099                            Map<String, Preference> preferencesMap = toPreferencesMap(xml);
100    
101                            return new PortalPreferencesImpl(
102                                    ownerId, ownerType, xml, preferencesMap, false);
103                    }
104                    catch (SystemException se) {
105                            throw se;
106                    }
107            }
108    
109            @Override
110            public PortletPreferencesImpl fromXML(
111                            long companyId, long ownerId, int ownerType, long plid,
112                            String portletId, String xml)
113                    throws SystemException {
114    
115                    try {
116                            Map<String, Preference> preferencesMap = toPreferencesMap(xml);
117    
118                            return new PortletPreferencesImpl(
119                                    companyId, ownerId, ownerType, plid, portletId, xml,
120                                    preferencesMap);
121                    }
122                    catch (SystemException se) {
123                            throw se;
124                    }
125            }
126    
127            /**
128             * @deprecated As of 6.2.0, replaced by {@link #fromXML(long, int, String)}
129             */
130            @Override
131            public PortalPreferences fromXML(
132                            long companyId, long ownerId, int ownerType, String xml)
133                    throws SystemException {
134    
135                    return fromXML(ownerId, ownerType, xml);
136            }
137    
138            @Override
139            public PortletPreferences getLayoutPortletSetup(
140                            Layout layout, String portletId)
141                    throws SystemException {
142    
143                    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
144                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
145    
146                    if (PortletConstants.hasUserId(portletId)) {
147                            ownerId = PortletConstants.getUserId(portletId);
148                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
149                    }
150    
151                    return PortletPreferencesLocalServiceUtil.getPreferences(
152                            layout.getCompanyId(), ownerId, ownerType, layout.getPlid(),
153                            portletId);
154            }
155    
156            @Override
157            public PortalPreferences getPortalPreferences(HttpServletRequest request)
158                    throws SystemException {
159    
160                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
161                            WebKeys.THEME_DISPLAY);
162    
163                    return getPortalPreferences(
164                            request.getSession(), themeDisplay.getUserId(),
165                            themeDisplay.isSignedIn());
166            }
167    
168            @Override
169            public PortalPreferences getPortalPreferences(
170                            HttpSession session, long userId, boolean signedIn)
171                    throws SystemException {
172    
173                    long ownerId = userId;
174                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
175    
176                    PortalPreferences portalPreferences = null;
177    
178                    if (signedIn) {
179                            PortalPreferencesWrapper portalPreferencesWrapper =
180                                    PortalPreferencesWrapperCacheUtil.get(ownerId, ownerType);
181    
182                            if (portalPreferencesWrapper == null) {
183                                    portalPreferencesWrapper =
184                                            (PortalPreferencesWrapper)
185                                                    PortalPreferencesLocalServiceUtil.getPreferences(
186                                                            ownerId, ownerType);
187    
188                                    portalPreferences =
189                                            portalPreferencesWrapper.getPortalPreferencesImpl();
190                            }
191                            else {
192                                    PortalPreferencesImpl portalPreferencesImpl =
193                                            portalPreferencesWrapper.getPortalPreferencesImpl();
194    
195                                    portalPreferences = portalPreferencesImpl.clone();
196                            }
197                    }
198                    else {
199                            if (session != null) {
200                                    portalPreferences = (PortalPreferences)session.getAttribute(
201                                            WebKeys.PORTAL_PREFERENCES);
202                            }
203    
204                            if (portalPreferences == null) {
205                                    PortalPreferencesWrapper portalPreferencesWrapper =
206                                            PortalPreferencesWrapperCacheUtil.get(ownerId, ownerType);
207    
208                                    if (portalPreferencesWrapper == null) {
209                                            portalPreferencesWrapper =
210                                                    (PortalPreferencesWrapper)
211                                                            PortalPreferencesLocalServiceUtil.getPreferences(
212                                                                    ownerId, ownerType);
213    
214                                            portalPreferences =
215                                                    portalPreferencesWrapper.getPortalPreferencesImpl();
216                                    }
217                                    else {
218                                            PortalPreferencesImpl portalPreferencesImpl =
219                                                    portalPreferencesWrapper.getPortalPreferencesImpl();
220    
221                                            portalPreferences = portalPreferencesImpl.clone();
222                                    }
223    
224                                    if (session != null) {
225                                            session.setAttribute(
226                                                    WebKeys.PORTAL_PREFERENCES, portalPreferences);
227                                    }
228                            }
229                    }
230    
231                    portalPreferences.setSignedIn(signedIn);
232                    portalPreferences.setUserId(userId);
233    
234                    return portalPreferences;
235            }
236    
237            /**
238             * @deprecated As of 6.2.0, replaced by {@link
239             *             #getPortalPreferences(HttpSession, long, boolean)}
240             */
241            @Override
242            public PortalPreferences getPortalPreferences(
243                            HttpSession session, long companyId, long userId, boolean signedIn)
244                    throws SystemException {
245    
246                    return getPortalPreferences(session, userId, signedIn);
247            }
248    
249            @Override
250            public PortalPreferences getPortalPreferences(long userId, boolean signedIn)
251                    throws SystemException {
252    
253                    return getPortalPreferences(null, userId, signedIn);
254            }
255    
256            /**
257             * @deprecated As of 6.2.0, replaced by {@link #getPortalPreferences(long,
258             *             boolean)}
259             */
260            @Override
261            public PortalPreferences getPortalPreferences(
262                            long companyId, long userId, boolean signedIn)
263                    throws SystemException {
264    
265                    return getPortalPreferences(userId, signedIn);
266            }
267    
268            @Override
269            public PortalPreferences getPortalPreferences(PortletRequest portletRequest)
270                    throws SystemException {
271    
272                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
273                            portletRequest);
274    
275                    return getPortalPreferences(request);
276            }
277    
278            @Override
279            public PortletPreferences getPortletPreferences(
280                            HttpServletRequest request, String portletId)
281                    throws PortalException, SystemException {
282    
283                    PortletPreferencesIds portletPreferencesIds = getPortletPreferencesIds(
284                            request, portletId);
285    
286                    return PortletPreferencesLocalServiceUtil.getPreferences(
287                            portletPreferencesIds);
288            }
289    
290            @Override
291            public PortletPreferencesIds getPortletPreferencesIds(
292                            HttpServletRequest request, Layout layout, String portletId)
293                    throws PortalException, SystemException {
294    
295                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
296                            WebKeys.THEME_DISPLAY);
297    
298                    long scopeGroupId = PortalUtil.getScopeGroupId(
299                            request, portletId, true);
300                    long userId = PortalUtil.getUserId(request);
301                    LayoutTypePortlet layoutTypePortlet =
302                            themeDisplay.getLayoutTypePortlet();
303    
304                    boolean modeEditGuest = false;
305    
306                    String portletMode = ParamUtil.getString(request, "p_p_mode");
307    
308                    if (portletMode.equals(LiferayPortletMode.EDIT_GUEST.toString()) ||
309                            ((layoutTypePortlet != null) &&
310                             layoutTypePortlet.hasModeEditGuestPortletId(portletId))) {
311    
312                            modeEditGuest = true;
313                    }
314    
315                    return getPortletPreferencesIds(
316                            scopeGroupId, userId, layout, portletId, modeEditGuest);
317            }
318    
319            @Override
320            public PortletPreferencesIds getPortletPreferencesIds(
321                            HttpServletRequest request, String portletId)
322                    throws PortalException, SystemException {
323    
324                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
325    
326                    return getPortletPreferencesIds(request, layout, portletId);
327            }
328    
329            @Override
330            public PortletPreferencesIds getPortletPreferencesIds(
331                            long scopeGroupId, long userId, Layout layout, String portletId,
332                            boolean modeEditGuest)
333                    throws PortalException, SystemException {
334    
335                    PermissionChecker permissionChecker =
336                            PermissionThreadLocal.getPermissionChecker();
337    
338                    String originalPortletId = portletId;
339    
340                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
341                            layout.getCompanyId(), portletId);
342    
343                    long ownerId = 0;
344                    int ownerType = 0;
345                    long plid = 0;
346    
347                    if (modeEditGuest) {
348                            boolean hasUpdateLayoutPermission = LayoutPermissionUtil.contains(
349                                    permissionChecker, layout, ActionKeys.UPDATE);
350    
351                            if (!layout.isPrivateLayout() && hasUpdateLayoutPermission) {
352                            }
353                            else {
354    
355                                    // Only users with the correct permissions can update guest
356                                    // preferences
357    
358                                    throw new PrincipalException();
359                            }
360                    }
361    
362                    if (PortletConstants.hasUserId(originalPortletId) &&
363                            (PortletConstants.getUserId(originalPortletId) == userId)) {
364    
365                            ownerId = userId;
366                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
367                            plid = layout.getPlid();
368                    }
369                    else if (portlet.isPreferencesCompanyWide()) {
370                            ownerId = layout.getCompanyId();
371                            ownerType = PortletKeys.PREFS_OWNER_TYPE_COMPANY;
372                            plid = PortletKeys.PREFS_PLID_SHARED;
373                            portletId = PortletConstants.getRootPortletId(portletId);
374                    }
375                    else {
376                            if (portlet.isPreferencesUniquePerLayout()) {
377                                    ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
378                                    ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
379                                    plid = layout.getPlid();
380    
381                                    if (portlet.isPreferencesOwnedByGroup()) {
382                                    }
383                                    else {
384                                            if ((userId <= 0) || modeEditGuest) {
385                                                    userId = UserLocalServiceUtil.getDefaultUserId(
386                                                            layout.getCompanyId());
387                                            }
388    
389                                            ownerId = userId;
390                                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
391                                    }
392                            }
393                            else {
394                                    plid = PortletKeys.PREFS_PLID_SHARED;
395    
396                                    if (portlet.isPreferencesOwnedByGroup()) {
397                                            ownerId = scopeGroupId;
398                                            ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
399                                            portletId = PortletConstants.getRootPortletId(portletId);
400                                    }
401                                    else {
402                                            if ((userId <= 0) || modeEditGuest) {
403                                                    userId = UserLocalServiceUtil.getDefaultUserId(
404                                                            layout.getCompanyId());
405                                            }
406    
407                                            ownerId = userId;
408                                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
409                                    }
410                            }
411                    }
412    
413                    return new PortletPreferencesIds(
414                            layout.getCompanyId(), ownerId, ownerType, plid, portletId);
415            }
416    
417            @Override
418            public PortletPreferences getPortletSetup(
419                            HttpServletRequest request, String portletId)
420                    throws PortalException, SystemException {
421    
422                    return getPortletSetup(request, portletId, null);
423            }
424    
425            @Override
426            public PortletPreferences getPortletSetup(
427                            HttpServletRequest request, String portletId,
428                            String defaultPreferences)
429                    throws PortalException, SystemException {
430    
431                    PortletRequest portletRequest = (PortletRequest)request.getAttribute(
432                            JavaConstants.JAVAX_PORTLET_REQUEST);
433    
434                    if (portletRequest instanceof ConfigurationPortletRequest) {
435                            PortletRequestWrapper portletRequestWrapper =
436                                    (PortletRequestWrapper)portletRequest;
437    
438                            return portletRequestWrapper.getPreferences();
439                    }
440    
441                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
442                            WebKeys.THEME_DISPLAY);
443    
444                    long scopeGroupId = PortalUtil.getScopeGroupId(
445                            request, portletId, true);
446    
447                    return getPortletSetup(
448                            scopeGroupId, themeDisplay.getLayout(), portletId,
449                            defaultPreferences);
450            }
451    
452            @Override
453            public PortletPreferences getPortletSetup(
454                            Layout layout, String portletId, String defaultPreferences)
455                    throws SystemException {
456    
457                    return getPortletSetup(
458                            LayoutConstants.DEFAULT_PLID, layout, portletId,
459                            defaultPreferences);
460            }
461    
462            @Override
463            public PortletPreferences getPortletSetup(
464                            long scopeGroupId, Layout layout, String portletId,
465                            String defaultPreferences)
466                    throws SystemException {
467    
468                    return getPortletSetup(
469                            scopeGroupId, layout, portletId, defaultPreferences, false);
470            }
471    
472            @Override
473            public PortletPreferences getPortletSetup(PortletRequest portletRequest)
474                    throws PortalException, SystemException {
475    
476                    String portletId = PortalUtil.getPortletId(portletRequest);
477    
478                    return getPortletSetup(portletRequest, portletId);
479            }
480    
481            @Override
482            public PortletPreferences getPortletSetup(
483                            PortletRequest portletRequest, String portletId)
484                    throws PortalException, SystemException {
485    
486                    if (portletRequest instanceof ConfigurationPortletRequest) {
487                            PortletRequestWrapper portletRequestWrapper =
488                                    (PortletRequestWrapper)portletRequest;
489    
490                            return portletRequestWrapper.getPreferences();
491                    }
492    
493                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
494                            portletRequest);
495    
496                    return getPortletSetup(request, portletId);
497            }
498    
499            @Override
500            public Map<Long, PortletPreferences> getPortletSetupMap(
501                            long companyId, long groupId, long ownerId, int ownerType,
502                            String portletId, boolean privateLayout)
503                    throws SystemException {
504    
505                    Map<Long, PortletPreferences> portletSetupMap =
506                            new HashMap<Long, PortletPreferences>();
507    
508                    List<com.liferay.portal.model.PortletPreferences>
509                            portletPreferencesList =
510                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
511                                            companyId, groupId, ownerId, ownerType, portletId,
512                                            privateLayout);
513    
514                    for (com.liferay.portal.model.PortletPreferences portletPreferences :
515                                    portletPreferencesList) {
516    
517                            PortletPreferences portletSetup =
518                                    PortletPreferencesLocalServiceUtil.getPreferences(
519                                            companyId, ownerId, ownerType, portletPreferences.getPlid(),
520                                            portletId);
521    
522                            portletSetupMap.put(portletPreferences.getPlid(), portletSetup);
523                    }
524    
525                    return portletSetupMap;
526            }
527    
528            @Override
529            public PortletPreferences getPreferences(HttpServletRequest request) {
530                    PortletRequest portletRequest = (PortletRequest)request.getAttribute(
531                            JavaConstants.JAVAX_PORTLET_REQUEST);
532    
533                    PortletPreferences portletPreferences = null;
534    
535                    if (portletRequest != null) {
536                            PortletPreferencesWrapper portletPreferencesWrapper =
537                                    (PortletPreferencesWrapper)portletRequest.getPreferences();
538    
539                            portletPreferences =
540                                    portletPreferencesWrapper.getPortletPreferencesImpl();
541                    }
542    
543                    return portletPreferences;
544            }
545    
546            @Override
547            public PreferencesValidator getPreferencesValidator(Portlet portlet) {
548                    return PortalUtil.getPreferencesValidator(portlet);
549            }
550    
551            @Override
552            public PortletPreferences getStrictLayoutPortletSetup(
553                            Layout layout, String portletId)
554                    throws SystemException {
555    
556                    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
557                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
558    
559                    if (PortletConstants.hasUserId(portletId)) {
560                            ownerId = PortletConstants.getUserId(portletId);
561                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
562                    }
563    
564                    return PortletPreferencesLocalServiceUtil.getStrictPreferences(
565                            layout.getCompanyId(), ownerId, ownerType, layout.getPlid(),
566                            portletId);
567            }
568    
569            @Override
570            public PortletPreferences getStrictPortletSetup(
571                            Layout layout, String portletId)
572                    throws SystemException {
573    
574                    return getPortletSetup(
575                            LayoutConstants.DEFAULT_PLID, layout, portletId, StringPool.BLANK,
576                            true);
577            }
578    
579            @Override
580            public String toXML(PortalPreferences portalPreferences) {
581                    PortalPreferencesImpl portalPreferencesImpl =
582                            (PortalPreferencesImpl)portalPreferences;
583    
584                    return portalPreferencesImpl.toXML();
585            }
586    
587            @Override
588            public String toXML(PortletPreferences portletPreferences) {
589                    PortletPreferencesImpl portletPreferencesImpl =
590                            (PortletPreferencesImpl)portletPreferences;
591    
592                    return portletPreferencesImpl.toXML();
593            }
594    
595            protected PortletPreferences getPortletSetup(
596                            long scopeGroupId, Layout layout, String portletId,
597                            String defaultPreferences, boolean strictMode)
598                    throws SystemException {
599    
600                    String originalPortletId = portletId;
601    
602                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
603                            layout.getCompanyId(), portletId);
604    
605                    boolean uniquePerLayout = false;
606                    boolean uniquePerGroup = false;
607    
608                    if (portlet.isPreferencesCompanyWide()) {
609                            portletId = PortletConstants.getRootPortletId(portletId);
610                    }
611                    else {
612                            if (portlet.isPreferencesUniquePerLayout()) {
613                                    uniquePerLayout = true;
614    
615                                    if (portlet.isPreferencesOwnedByGroup()) {
616                                            uniquePerGroup = true;
617                                    }
618                            }
619                            else {
620                                    if (portlet.isPreferencesOwnedByGroup()) {
621                                            uniquePerGroup = true;
622                                            portletId = PortletConstants.getRootPortletId(portletId);
623                                    }
624                            }
625                    }
626    
627                    long ownerId = PortletKeys.PREFS_OWNER_ID_DEFAULT;
628                    int ownerType = PortletKeys.PREFS_OWNER_TYPE_LAYOUT;
629                    long plid = layout.getPlid();
630    
631                    Group group = GroupLocalServiceUtil.fetchGroup(scopeGroupId);
632    
633                    if ((group != null) && group.isLayout()) {
634                            plid = group.getClassPK();
635                    }
636    
637                    if (PortletConstants.hasUserId(originalPortletId)) {
638                            ownerId = PortletConstants.getUserId(originalPortletId);
639                            ownerType = PortletKeys.PREFS_OWNER_TYPE_USER;
640                    }
641                    else if (!uniquePerLayout) {
642                            plid = PortletKeys.PREFS_PLID_SHARED;
643    
644                            if (uniquePerGroup) {
645                                    if (scopeGroupId > LayoutConstants.DEFAULT_PLID) {
646                                            ownerId = scopeGroupId;
647                                    }
648                                    else {
649                                            ownerId = layout.getGroupId();
650                                    }
651    
652                                    ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
653                            }
654                            else {
655                                    ownerId = layout.getCompanyId();
656                                    ownerType = PortletKeys.PREFS_OWNER_TYPE_COMPANY;
657                            }
658                    }
659    
660                    if (strictMode) {
661                            return PortletPreferencesLocalServiceUtil.getStrictPreferences(
662                                    layout.getCompanyId(), ownerId, ownerType, plid, portletId);
663                    }
664    
665                    return PortletPreferencesLocalServiceUtil.getPreferences(
666                            layout.getCompanyId(), ownerId, ownerType, plid, portletId,
667                            defaultPreferences);
668            }
669    
670            protected Preference readPreference(XMLEventReader xmlEventReader)
671                    throws XMLStreamException {
672    
673                    String name = null;
674                    List<String> values = new ArrayList<String>();
675                    boolean readOnly = false;
676    
677                    while (xmlEventReader.hasNext()) {
678                            XMLEvent xmlEvent = xmlEventReader.nextEvent();
679    
680                            if (xmlEvent.isStartElement()) {
681                                    StartElement startElement = xmlEvent.asStartElement();
682    
683                                    String elementName = startElement.getName().getLocalPart();
684    
685                                    if (elementName.equals("name")) {
686                                            name = StAXReaderUtil.read(xmlEventReader);
687                                    }
688                                    else if (elementName.equals("value")) {
689                                            String value = StAXReaderUtil.read(xmlEventReader);
690    
691                                            values.add(value);
692                                    }
693                                    else if (elementName.equals("read-only")) {
694                                            String value = StAXReaderUtil.read(xmlEventReader);
695    
696                                            readOnly = GetterUtil.getBoolean(value);
697                                    }
698                            }
699                            else if (xmlEvent.isEndElement()) {
700                                    EndElement endElement = xmlEvent.asEndElement();
701    
702                                    String elementName = endElement.getName().getLocalPart();
703    
704                                    if (elementName.equals("preference")) {
705                                            break;
706                                    }
707                            }
708                    }
709    
710                    return new Preference(
711                            name, values.toArray(new String[values.size()]), readOnly);
712            }
713    
714            protected Map<String, Preference> toPreferencesMap(String xml)
715                    throws SystemException {
716    
717                    if (Validator.isNull(xml)) {
718                            return Collections.emptyMap();
719                    }
720    
721                    Map<String, Preference> preferencesMap = _preferencesMapPortalCache.get(
722                            xml);
723    
724                    if (preferencesMap != null) {
725                            return preferencesMap;
726                    }
727    
728                    XMLEventReader xmlEventReader = null;
729    
730                    try {
731                            XMLInputFactory xmlInputFactory =
732                                    StAXReaderUtil.getXMLInputFactory();
733    
734                            xmlEventReader = xmlInputFactory.createXMLEventReader(
735                                    new UnsyncStringReader(xml));
736    
737                            while (xmlEventReader.hasNext()) {
738                                    XMLEvent xmlEvent = xmlEventReader.nextEvent();
739    
740                                    if (xmlEvent.isStartElement()) {
741                                            StartElement startElement = xmlEvent.asStartElement();
742    
743                                            String elementName = startElement.getName().getLocalPart();
744    
745                                            if (elementName.equals("preference")) {
746                                                    Preference preference = readPreference(xmlEventReader);
747    
748                                                    if (preferencesMap == null) {
749                                                            preferencesMap = new HashMap<String, Preference>();
750                                                    }
751    
752                                                    preferencesMap.put(preference.getName(), preference);
753                                            }
754                                    }
755                            }
756                    }
757                    catch (XMLStreamException xse) {
758                            throw new SystemException(xse);
759                    }
760                    finally {
761                            if (xmlEventReader != null) {
762                                    try {
763                                            xmlEventReader.close();
764                                    }
765                                    catch (XMLStreamException xse) {
766                                    }
767                            }
768                    }
769    
770                    if (preferencesMap == null) {
771                            preferencesMap = Collections.emptyMap();
772                    }
773    
774                    _preferencesMapPortalCache.put(xml, preferencesMap);
775    
776                    return preferencesMap;
777            }
778    
779            private PortalCache<String, Map<String, Preference>>
780                    _preferencesMapPortalCache = SingleVMPoolUtil.getCache(
781                            PortletPreferencesFactoryImpl.class.getName());
782    
783    }