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.assetpublisher.util;
016    
017    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.Property;
020    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021    import com.liferay.portal.kernel.dao.orm.QueryUtil;
022    import com.liferay.portal.kernel.exception.PortalException;
023    import com.liferay.portal.kernel.exception.SystemException;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.servlet.SessionMessages;
027    import com.liferay.portal.kernel.util.Accessor;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.ListUtil;
031    import com.liferay.portal.kernel.util.LocaleUtil;
032    import com.liferay.portal.kernel.util.LocalizationUtil;
033    import com.liferay.portal.kernel.util.ParamUtil;
034    import com.liferay.portal.kernel.util.PrefsPropsUtil;
035    import com.liferay.portal.kernel.util.PrimitiveLongList;
036    import com.liferay.portal.kernel.util.PropsKeys;
037    import com.liferay.portal.kernel.util.PropsUtil;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.StringUtil;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.xml.Document;
042    import com.liferay.portal.kernel.xml.Element;
043    import com.liferay.portal.kernel.xml.SAXReaderUtil;
044    import com.liferay.portal.model.Group;
045    import com.liferay.portal.model.GroupConstants;
046    import com.liferay.portal.model.Layout;
047    import com.liferay.portal.model.PortletConstants;
048    import com.liferay.portal.model.User;
049    import com.liferay.portal.security.auth.PrincipalThreadLocal;
050    import com.liferay.portal.security.permission.ActionKeys;
051    import com.liferay.portal.security.permission.PermissionChecker;
052    import com.liferay.portal.service.GroupLocalServiceUtil;
053    import com.liferay.portal.service.LayoutLocalServiceUtil;
054    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
055    import com.liferay.portal.service.SubscriptionLocalServiceUtil;
056    import com.liferay.portal.service.permission.GroupPermissionUtil;
057    import com.liferay.portal.service.permission.PortletPermissionUtil;
058    import com.liferay.portal.service.persistence.PortletPreferencesActionableDynamicQuery;
059    import com.liferay.portal.theme.ThemeDisplay;
060    import com.liferay.portal.util.PortalUtil;
061    import com.liferay.portal.util.PortletKeys;
062    import com.liferay.portal.util.PropsValues;
063    import com.liferay.portal.util.SubscriptionSender;
064    import com.liferay.portal.util.WebKeys;
065    import com.liferay.portlet.PortletPreferencesFactoryUtil;
066    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
067    import com.liferay.portlet.asset.model.AssetCategory;
068    import com.liferay.portlet.asset.model.AssetEntry;
069    import com.liferay.portlet.asset.model.AssetRenderer;
070    import com.liferay.portlet.asset.model.AssetRendererFactory;
071    import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
072    import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
073    import com.liferay.portlet.asset.service.AssetEntryServiceUtil;
074    import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
075    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
076    import com.liferay.portlet.expando.model.ExpandoBridge;
077    import com.liferay.portlet.sites.util.SitesUtil;
078    import com.liferay.util.ContentUtil;
079    
080    import java.io.IOException;
081    import java.io.Serializable;
082    
083    import java.util.ArrayList;
084    import java.util.HashMap;
085    import java.util.Iterator;
086    import java.util.List;
087    import java.util.Locale;
088    import java.util.Map;
089    
090    import javax.portlet.PortletException;
091    import javax.portlet.PortletPreferences;
092    import javax.portlet.PortletRequest;
093    
094    import javax.servlet.http.HttpServletRequest;
095    import javax.servlet.http.HttpSession;
096    
097    /**
098     * @author Raymond Aug??
099     * @author Julio Camarero
100     */
101    public class AssetPublisherImpl implements AssetPublisher {
102    
103            @Override
104            public void addAndStoreSelection(
105                            PortletRequest portletRequest, String className, long classPK,
106                            int assetEntryOrder)
107                    throws Exception {
108    
109                    String referringPortletResource = ParamUtil.getString(
110                            portletRequest, "referringPortletResource");
111    
112                    if (Validator.isNull(referringPortletResource)) {
113                            return;
114                    }
115    
116                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
117                            WebKeys.THEME_DISPLAY);
118    
119                    Layout layout = LayoutLocalServiceUtil.getLayout(
120                            themeDisplay.getRefererPlid());
121    
122                    PortletPreferences portletPreferences =
123                            PortletPreferencesFactoryUtil.getPortletSetup(
124                                    themeDisplay.getScopeGroupId(), layout,
125                                    referringPortletResource, null);
126    
127                    String selectionStyle = portletPreferences.getValue(
128                            "selectionStyle", "dynamic");
129    
130                    if (selectionStyle.equals("dynamic")) {
131                            return;
132                    }
133    
134                    AssetEntry assetEntry = AssetEntryLocalServiceUtil.getEntry(
135                            className, classPK);
136    
137                    addSelection(
138                            themeDisplay, portletPreferences, referringPortletResource,
139                            assetEntry.getEntryId(), assetEntryOrder, className);
140    
141                    portletPreferences.store();
142            }
143    
144            @Override
145            public void addRecentFolderId(
146                    PortletRequest portletRequest, String className, long classPK) {
147    
148                    _getRecentFolderIds(portletRequest).put(className, classPK);
149            }
150    
151            @Override
152            public void addSelection(
153                            PortletRequest portletRequest,
154                            PortletPreferences portletPreferences, String portletId)
155                    throws Exception {
156    
157                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
158                            WebKeys.THEME_DISPLAY);
159    
160                    long assetEntryId = ParamUtil.getLong(portletRequest, "assetEntryId");
161                    int assetEntryOrder = ParamUtil.getInteger(
162                            portletRequest, "assetEntryOrder");
163                    String assetEntryType = ParamUtil.getString(
164                            portletRequest, "assetEntryType");
165    
166                    addSelection(
167                            themeDisplay, portletPreferences, portletId, assetEntryId,
168                            assetEntryOrder, assetEntryType);
169            }
170    
171            @Override
172            public void addSelection(
173                            ThemeDisplay themeDisplay, PortletPreferences portletPreferences,
174                            String portletId, long assetEntryId, int assetEntryOrder,
175                            String assetEntryType)
176                    throws Exception {
177    
178                    AssetEntry assetEntry = AssetEntryLocalServiceUtil.getEntry(
179                            assetEntryId);
180    
181                    String[] assetEntryXmls = portletPreferences.getValues(
182                            "assetEntryXml", new String[0]);
183    
184                    String assetEntryXml = _getAssetEntryXml(
185                            assetEntryType, assetEntry.getClassUuid());
186    
187                    if (!ArrayUtil.contains(assetEntryXmls, assetEntryXml)) {
188                            if (assetEntryOrder > -1) {
189                                    assetEntryXmls[assetEntryOrder] = assetEntryXml;
190                            }
191                            else {
192                                    assetEntryXmls = ArrayUtil.append(
193                                            assetEntryXmls, assetEntryXml);
194                            }
195    
196                            portletPreferences.setValues("assetEntryXml", assetEntryXmls);
197                    }
198    
199                    long plid = themeDisplay.getRefererPlid();
200    
201                    if (plid == 0) {
202                            plid = themeDisplay.getPlid();
203                    }
204    
205                    List<AssetEntry> assetEntries = new ArrayList<AssetEntry>();
206    
207                    assetEntries.add(assetEntry);
208    
209                    notifySubscribers(portletPreferences, plid, portletId, assetEntries);
210            }
211    
212            @Override
213            public void addUserAttributes(
214                            User user, String[] customUserAttributeNames,
215                            AssetEntryQuery assetEntryQuery)
216                    throws Exception {
217    
218                    if ((user == null) || (customUserAttributeNames.length == 0)) {
219                            return;
220                    }
221    
222                    Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
223                            user.getCompanyId());
224    
225                    long[] allCategoryIds = assetEntryQuery.getAllCategoryIds();
226    
227                    PrimitiveLongList allCategoryIdsList = new PrimitiveLongList(
228                            allCategoryIds.length + customUserAttributeNames.length);
229    
230                    allCategoryIdsList.addAll(allCategoryIds);
231    
232                    for (String customUserAttributeName : customUserAttributeNames) {
233                            ExpandoBridge userCustomAttributes = user.getExpandoBridge();
234    
235                            Serializable userCustomFieldValue =
236                                    userCustomAttributes.getAttribute(customUserAttributeName);
237    
238                            if (userCustomFieldValue == null) {
239                                    continue;
240                            }
241    
242                            String userCustomFieldValueString = userCustomFieldValue.toString();
243    
244                            List<AssetCategory> assetCategories =
245                                    AssetCategoryLocalServiceUtil.search(
246                                            companyGroup.getGroupId(), userCustomFieldValueString,
247                                            new String[0], QueryUtil.ALL_POS, QueryUtil.ALL_POS);
248    
249                            for (AssetCategory assetCategory : assetCategories) {
250                                    allCategoryIdsList.add(assetCategory.getCategoryId());
251                            }
252                    }
253    
254                    assetEntryQuery.setAllCategoryIds(allCategoryIdsList.getArray());
255            }
256    
257            @Override
258            public void checkAssetEntries() throws Exception {
259                    ActionableDynamicQuery actionableDynamicQuery =
260                            new PortletPreferencesActionableDynamicQuery() {
261    
262                            @Override
263                            protected void addCriteria(DynamicQuery dynamicQuery) {
264                                    Property property = PropertyFactoryUtil.forName("portletId");
265    
266                                    String portletId =
267                                            PortletKeys.ASSET_PUBLISHER +
268                                                    PortletConstants.INSTANCE_SEPARATOR +
269                                                            StringPool.PERCENT;
270    
271                                    dynamicQuery.add(property.like(portletId));
272                            }
273    
274                            @Override
275                            protected void performAction(Object object)
276                                    throws PortalException, SystemException {
277    
278                                    com.liferay.portal.model.PortletPreferences portletPreferences =
279                                            (com.liferay.portal.model.PortletPreferences)object;
280    
281                                    _checkAssetEntries(portletPreferences);
282                            }
283    
284                    };
285    
286                    actionableDynamicQuery.performActions();
287            }
288    
289            @Override
290            public List<AssetEntry> getAssetEntries(
291                            PortletPreferences preferences, Layout layout, long scopeGroupId,
292                            int max, boolean checkPermission)
293                    throws PortalException, SystemException {
294    
295                    AssetEntryQuery assetEntryQuery = getAssetEntryQuery(
296                            preferences, new long[] {scopeGroupId});
297    
298                    boolean anyAssetType = GetterUtil.getBoolean(
299                            preferences.getValue("anyAssetType", null), true);
300    
301                    if (!anyAssetType) {
302                            long[] availableClassNameIds =
303                                    AssetRendererFactoryRegistryUtil.getClassNameIds(
304                                            layout.getCompanyId());
305    
306                            long[] classNameIds = getClassNameIds(
307                                    preferences, availableClassNameIds);
308    
309                            assetEntryQuery.setClassNameIds(classNameIds);
310                    }
311    
312                    long[] classTypeIds = GetterUtil.getLongValues(
313                            preferences.getValues("classTypeIds", null));
314    
315                    assetEntryQuery.setClassTypeIds(classTypeIds);
316    
317                    boolean enablePermissions = GetterUtil.getBoolean(
318                            preferences.getValue("enablePermissions", null));
319    
320                    assetEntryQuery.setEnablePermissions(enablePermissions);
321    
322                    assetEntryQuery.setEnd(max);
323    
324                    boolean excludeZeroViewCount = GetterUtil.getBoolean(
325                            preferences.getValue("excludeZeroViewCount", null));
326    
327                    assetEntryQuery.setExcludeZeroViewCount(excludeZeroViewCount);
328    
329                    long[] groupIds = getGroupIds(preferences, scopeGroupId, layout);
330    
331                    assetEntryQuery.setGroupIds(groupIds);
332    
333                    boolean showOnlyLayoutAssets = GetterUtil.getBoolean(
334                            preferences.getValue("showOnlyLayoutAssets", null));
335    
336                    if (showOnlyLayoutAssets) {
337                            assetEntryQuery.setLayout(layout);
338                    }
339    
340                    String orderByColumn1 = GetterUtil.getString(
341                            preferences.getValue("orderByColumn1", "modifiedDate"));
342    
343                    assetEntryQuery.setOrderByCol1(orderByColumn1);
344    
345                    String orderByColumn2 = GetterUtil.getString(
346                            preferences.getValue("orderByColumn2", "title"));
347    
348                    assetEntryQuery.setOrderByCol2(orderByColumn2);
349    
350                    String orderByType1 = GetterUtil.getString(
351                            preferences.getValue("orderByType1", "DESC"));
352    
353                    assetEntryQuery.setOrderByType1(orderByType1);
354    
355                    String orderByType2 = GetterUtil.getString(
356                            preferences.getValue("orderByType2", "ASC"));
357    
358                    assetEntryQuery.setOrderByType2(orderByType2);
359    
360                    assetEntryQuery.setStart(0);
361    
362                    if (checkPermission) {
363                            return AssetEntryServiceUtil.getEntries(assetEntryQuery);
364                    }
365                    else {
366                            return AssetEntryLocalServiceUtil.getEntries(assetEntryQuery);
367                    }
368            }
369    
370            @Override
371            public List<AssetEntry> getAssetEntries(
372                            PortletRequest portletRequest,
373                            PortletPreferences portletPreferences,
374                            PermissionChecker permissionChecker, long[] groupIds,
375                            String[] assetEntryXmls, boolean deleteMissingAssetEntries,
376                            boolean checkPermission)
377                    throws Exception {
378    
379                    List<AssetEntry> assetEntries = new ArrayList<AssetEntry>();
380    
381                    List<String> missingAssetEntryUuids = new ArrayList<String>();
382    
383                    for (String assetEntryXml : assetEntryXmls) {
384                            Document document = SAXReaderUtil.read(assetEntryXml);
385    
386                            Element rootElement = document.getRootElement();
387    
388                            String assetEntryUuid = rootElement.elementText("asset-entry-uuid");
389    
390                            AssetEntry assetEntry = null;
391    
392                            for (long groupId : groupIds) {
393                                    assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
394                                            groupId, assetEntryUuid);
395    
396                                    if (assetEntry != null) {
397                                            break;
398                                    }
399                            }
400    
401                            if (assetEntry == null) {
402                                    if (deleteMissingAssetEntries) {
403                                            missingAssetEntryUuids.add(assetEntryUuid);
404                                    }
405    
406                                    continue;
407                            }
408    
409                            if (!assetEntry.isVisible()) {
410                                    continue;
411                            }
412    
413                            AssetRendererFactory assetRendererFactory =
414                                    AssetRendererFactoryRegistryUtil.
415                                            getAssetRendererFactoryByClassName(
416                                                    assetEntry.getClassName());
417    
418                            AssetRenderer assetRenderer = assetRendererFactory.getAssetRenderer(
419                                    assetEntry.getClassPK());
420    
421                            if (!assetRendererFactory.isActive(
422                                            permissionChecker.getCompanyId())) {
423    
424                                    if (deleteMissingAssetEntries) {
425                                            missingAssetEntryUuids.add(assetEntryUuid);
426                                    }
427    
428                                    continue;
429                            }
430    
431                            if (checkPermission &&
432                                    (!assetRenderer.isDisplayable() ||
433                                     !assetRenderer.hasViewPermission(permissionChecker))) {
434    
435                                    continue;
436                            }
437    
438                            assetEntries.add(assetEntry);
439                    }
440    
441                    if (deleteMissingAssetEntries) {
442                            AssetPublisherUtil.removeAndStoreSelection(
443                                    missingAssetEntryUuids, portletPreferences);
444    
445                            if (!missingAssetEntryUuids.isEmpty()) {
446                                    SessionMessages.add(
447                                            portletRequest, "deletedMissingAssetEntries",
448                                            missingAssetEntryUuids);
449                            }
450                    }
451    
452                    return assetEntries;
453            }
454    
455            @Override
456            public AssetEntryQuery getAssetEntryQuery(
457                            PortletPreferences portletPreferences, long[] scopeGroupIds)
458                    throws PortalException, SystemException {
459    
460                    AssetEntryQuery assetEntryQuery = new AssetEntryQuery();
461    
462                    long[] allAssetCategoryIds = new long[0];
463                    long[] anyAssetCategoryIds = new long[0];
464                    long[] notAllAssetCategoryIds = new long[0];
465                    long[] notAnyAssetCategoryIds = new long[0];
466    
467                    String[] allAssetTagNames = new String[0];
468                    String[] anyAssetTagNames = new String[0];
469                    String[] notAllAssetTagNames = new String[0];
470                    String[] notAnyAssetTagNames = new String[0];
471    
472                    for (int i = 0; true; i++) {
473                            String[] queryValues = portletPreferences.getValues(
474                                    "queryValues" + i, null);
475    
476                            if ((queryValues == null) || (queryValues.length == 0)) {
477                                    break;
478                            }
479    
480                            boolean queryContains = GetterUtil.getBoolean(
481                                    portletPreferences.getValue(
482                                            "queryContains" + i, StringPool.BLANK));
483                            boolean queryAndOperator = GetterUtil.getBoolean(
484                                    portletPreferences.getValue(
485                                            "queryAndOperator" + i, StringPool.BLANK));
486                            String queryName = portletPreferences.getValue(
487                                    "queryName" + i, StringPool.BLANK);
488    
489                            if (Validator.equals(queryName, "assetCategories")) {
490                                    long[] assetCategoryIds = GetterUtil.getLongValues(queryValues);
491    
492                                    if (queryContains && queryAndOperator) {
493                                            allAssetCategoryIds = assetCategoryIds;
494                                    }
495                                    else if (queryContains && !queryAndOperator) {
496                                            anyAssetCategoryIds = assetCategoryIds;
497                                    }
498                                    else if (!queryContains && queryAndOperator) {
499                                            notAllAssetCategoryIds = assetCategoryIds;
500                                    }
501                                    else {
502                                            notAnyAssetCategoryIds = assetCategoryIds;
503                                    }
504                            }
505                            else {
506                                    if (queryContains && queryAndOperator) {
507                                            allAssetTagNames = queryValues;
508                                    }
509                                    else if (queryContains && !queryAndOperator) {
510                                            anyAssetTagNames = queryValues;
511                                    }
512                                    else if (!queryContains && queryAndOperator) {
513                                            notAllAssetTagNames = queryValues;
514                                    }
515                                    else {
516                                            notAnyAssetTagNames = queryValues;
517                                    }
518                            }
519                    }
520    
521                    assetEntryQuery.setAllCategoryIds(allAssetCategoryIds);
522    
523                    for (String assetTagName : allAssetTagNames) {
524                            long[] allAssetTagIds = AssetTagLocalServiceUtil.getTagIds(
525                                    scopeGroupIds, assetTagName);
526    
527                            assetEntryQuery.addAllTagIdsArray(allAssetTagIds);
528                    }
529    
530                    assetEntryQuery.setAnyCategoryIds(anyAssetCategoryIds);
531    
532                    long[] anyAssetTagIds = AssetTagLocalServiceUtil.getTagIds(
533                            scopeGroupIds, anyAssetTagNames);
534    
535                    assetEntryQuery.setAnyTagIds(anyAssetTagIds);
536    
537                    assetEntryQuery.setNotAllCategoryIds(notAllAssetCategoryIds);
538    
539                    for (String assetTagName : notAllAssetTagNames) {
540                            long[] notAllAssetTagIds = AssetTagLocalServiceUtil.getTagIds(
541                                    scopeGroupIds, assetTagName);
542    
543                            assetEntryQuery.addNotAllTagIdsArray(notAllAssetTagIds);
544                    }
545    
546                    assetEntryQuery.setNotAnyCategoryIds(notAnyAssetCategoryIds);
547    
548                    long[] notAnyAssetTagIds = AssetTagLocalServiceUtil.getTagIds(
549                            scopeGroupIds, notAnyAssetTagNames);
550    
551                    assetEntryQuery.setNotAnyTagIds(notAnyAssetTagIds);
552    
553                    return assetEntryQuery;
554            }
555    
556            @Override
557            public String[] getAssetTagNames(
558                            PortletPreferences portletPreferences, long scopeGroupId)
559                    throws Exception {
560    
561                    String[] allAssetTagNames = new String[0];
562    
563                    for (int i = 0; true; i++) {
564                            String[] queryValues = portletPreferences.getValues(
565                                    "queryValues" + i, null);
566    
567                            if ((queryValues == null) || (queryValues.length == 0)) {
568                                    break;
569                            }
570    
571                            boolean queryContains = GetterUtil.getBoolean(
572                                    portletPreferences.getValue(
573                                            "queryContains" + i, StringPool.BLANK));
574                            boolean queryAndOperator = GetterUtil.getBoolean(
575                                    portletPreferences.getValue(
576                                            "queryAndOperator" + i, StringPool.BLANK));
577                            String queryName = portletPreferences.getValue(
578                                    "queryName" + i, StringPool.BLANK);
579    
580                            if (!Validator.equals(queryName, "assetCategories") &&
581                                    queryContains && queryAndOperator) {
582    
583                                    allAssetTagNames = queryValues;
584                            }
585                    }
586    
587                    return allAssetTagNames;
588            }
589    
590            @Override
591            public String getClassName(AssetRendererFactory assetRendererFactory) {
592                    Class<?> clazz = assetRendererFactory.getClass();
593    
594                    String className = clazz.getName();
595    
596                    int pos = className.lastIndexOf(StringPool.PERIOD);
597    
598                    return className.substring(pos + 1);
599            }
600    
601            @Override
602            public long[] getClassNameIds(
603                    PortletPreferences portletPreferences, long[] availableClassNameIds) {
604    
605                    boolean anyAssetType = GetterUtil.getBoolean(
606                            portletPreferences.getValue(
607                                    "anyAssetType", Boolean.TRUE.toString()));
608                    String selectionStyle = portletPreferences.getValue(
609                            "selectionStyle", "dynamic");
610    
611                    if (anyAssetType || selectionStyle.equals("manual")) {
612                            return availableClassNameIds;
613                    }
614    
615                    long defaultClassNameId = GetterUtil.getLong(
616                            portletPreferences.getValue("anyAssetType", null));
617    
618                    if (defaultClassNameId > 0) {
619                            return new long[] {defaultClassNameId};
620                    }
621    
622                    long[] classNameIds = GetterUtil.getLongValues(
623                            portletPreferences.getValues("classNameIds", null));
624    
625                    if ((classNameIds != null) && (classNameIds.length > 0)) {
626                            return classNameIds;
627                    }
628                    else {
629                            return availableClassNameIds;
630                    }
631            }
632    
633            @Override
634            public Long[] getClassTypeIds(
635                    PortletPreferences portletPreferences, String className,
636                    Long[] availableClassTypeIds) {
637    
638                    boolean anyAssetType = GetterUtil.getBoolean(
639                            portletPreferences.getValue(
640                                    "anyClassType" + className, Boolean.TRUE.toString()));
641    
642                    if (anyAssetType) {
643                            return availableClassTypeIds;
644                    }
645    
646                    long defaultClassTypeId = GetterUtil.getLong(
647                            portletPreferences.getValue("anyClassType" + className, null));
648    
649                    if (defaultClassTypeId > 0) {
650                            return new Long[] {defaultClassTypeId};
651                    }
652    
653                    Long[] classTypeIds = ArrayUtil.toArray(
654                            StringUtil.split(
655                                    portletPreferences.getValue(
656                                            "classTypeIds" + className, null), 0L));
657    
658                    if (classTypeIds != null) {
659                            return classTypeIds;
660                    }
661                    else {
662                            return availableClassTypeIds;
663                    }
664            }
665    
666            @Override
667            public Map<Locale, String> getEmailAssetEntryAddedBodyMap(
668                    PortletPreferences preferences) {
669    
670                    Map<Locale, String> map = LocalizationUtil.getLocalizationMap(
671                            preferences, "emailAssetEntryAddedBody");
672    
673                    Locale defaultLocale = LocaleUtil.getSiteDefault();
674    
675                    String defaultValue = map.get(defaultLocale);
676    
677                    if (Validator.isNotNull(defaultValue)) {
678                            return map;
679                    }
680    
681                    map.put(
682                            defaultLocale,
683                            ContentUtil.get(
684                                    PropsUtil.get(
685                                            PropsKeys.ASSET_PUBLISHER_EMAIL_ASSET_ENTRY_ADDED_BODY)));
686    
687                    return map;
688            }
689    
690            @Override
691            public boolean getEmailAssetEntryAddedEnabled(
692                    PortletPreferences preferences) {
693    
694                    String emailAssetEntryAddedEnabled = preferences.getValue(
695                            "emailAssetEntryAddedEnabled", StringPool.BLANK);
696    
697                    if (Validator.isNotNull(emailAssetEntryAddedEnabled)) {
698                            return GetterUtil.getBoolean(emailAssetEntryAddedEnabled);
699                    }
700                    else {
701                            return PropsValues.ASSET_PUBLISHER_EMAIL_ASSET_ENTRY_ADDED_ENABLED;
702                    }
703            }
704    
705            @Override
706            public Map<Locale, String> getEmailAssetEntryAddedSubjectMap(
707                    PortletPreferences preferences) {
708    
709                    Map<Locale, String> map = LocalizationUtil.getLocalizationMap(
710                            preferences, "emailAssetEntryAddedSubject");
711    
712                    Locale defaultLocale = LocaleUtil.getSiteDefault();
713    
714                    String defaultValue = map.get(defaultLocale);
715    
716                    if (Validator.isNotNull(defaultValue)) {
717                            return map;
718                    }
719    
720                    map.put(
721                            defaultLocale,
722                            ContentUtil.get(
723                                    PropsUtil.get(
724                                            PropsKeys.ASSET_PUBLISHER_EMAIL_ASSET_ENTRY_ADDED_SUBJECT))
725                    );
726    
727                    return map;
728            }
729    
730            @Override
731            public String getEmailFromAddress(
732                            PortletPreferences preferences, long companyId)
733                    throws SystemException {
734    
735                    return PortalUtil.getEmailFromAddress(
736                            preferences, companyId,
737                            PropsValues.ASSET_PUBLISHER_EMAIL_FROM_ADDRESS);
738            }
739    
740            @Override
741            public String getEmailFromName(
742                            PortletPreferences preferences, long companyId)
743                    throws SystemException {
744    
745                    return PortalUtil.getEmailFromName(
746                            preferences, companyId,
747                            PropsValues.ASSET_PUBLISHER_EMAIL_FROM_NAME);
748            }
749    
750            @Override
751            public long getGroupIdFromScopeId(
752                            String scopeId, long siteGroupId, boolean privateLayout)
753                    throws PortalException, SystemException {
754    
755                    if (scopeId.startsWith(SCOPE_ID_CHILD_GROUP_PREFIX)) {
756                            String scopeIdSuffix = scopeId.substring(
757                                    SCOPE_ID_CHILD_GROUP_PREFIX.length());
758    
759                            return GetterUtil.getLong(scopeIdSuffix);
760                    }
761                    else if (scopeId.startsWith(SCOPE_ID_GROUP_PREFIX)) {
762                            String scopeIdSuffix = scopeId.substring(
763                                    SCOPE_ID_GROUP_PREFIX.length());
764    
765                            if (scopeIdSuffix.equals(GroupConstants.DEFAULT)) {
766                                    return siteGroupId;
767                            }
768    
769                            return GetterUtil.getLong(scopeIdSuffix);
770                    }
771                    else if (scopeId.startsWith(SCOPE_ID_LAYOUT_UUID_PREFIX)) {
772                            String layoutUuid = scopeId.substring(
773                                    SCOPE_ID_LAYOUT_UUID_PREFIX.length());
774    
775                            Layout scopeIdLayout =
776                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
777                                            layoutUuid, siteGroupId, privateLayout);
778    
779                            Group scopeIdGroup = null;
780    
781                            if (scopeIdLayout.hasScopeGroup()) {
782                                    scopeIdGroup = scopeIdLayout.getScopeGroup();
783                            }
784                            else {
785                                    scopeIdGroup = GroupLocalServiceUtil.addGroup(
786                                            PrincipalThreadLocal.getUserId(),
787                                            GroupConstants.DEFAULT_PARENT_GROUP_ID,
788                                            Layout.class.getName(), scopeIdLayout.getPlid(),
789                                            GroupConstants.DEFAULT_LIVE_GROUP_ID,
790                                            String.valueOf(scopeIdLayout.getPlid()), null, 0, true,
791                                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, null, false,
792                                            true, null);
793                            }
794    
795                            return scopeIdGroup.getGroupId();
796                    }
797                    else if (scopeId.startsWith(SCOPE_ID_LAYOUT_PREFIX)) {
798    
799                            // Legacy preferences
800    
801                            String scopeIdSuffix = scopeId.substring(
802                                    SCOPE_ID_LAYOUT_PREFIX.length());
803    
804                            long scopeIdLayoutId = GetterUtil.getLong(scopeIdSuffix);
805    
806                            Layout scopeIdLayout = LayoutLocalServiceUtil.getLayout(
807                                    siteGroupId, privateLayout, scopeIdLayoutId);
808    
809                            Group scopeIdGroup = scopeIdLayout.getScopeGroup();
810    
811                            return scopeIdGroup.getGroupId();
812                    }
813                    else if (scopeId.startsWith(SCOPE_ID_PARENT_GROUP_PREFIX)) {
814                            String scopeIdSuffix = scopeId.substring(
815                                    SCOPE_ID_PARENT_GROUP_PREFIX.length());
816    
817                            return GetterUtil.getLong(scopeIdSuffix);
818                    }
819                    else {
820                            throw new IllegalArgumentException("Invalid scope ID " + scopeId);
821                    }
822            }
823    
824            @Override
825            public long[] getGroupIds(
826                    PortletPreferences portletPreferences, long scopeGroupId,
827                    Layout layout) {
828    
829                    String[] scopeIds = portletPreferences.getValues(
830                            "scopeIds", new String[] {SCOPE_ID_GROUP_PREFIX + scopeGroupId});
831    
832                    long[] groupIds = new long[scopeIds.length];
833    
834                    int i = 0;
835    
836                    for (String scopeId : scopeIds) {
837                            try {
838                                    groupIds[i] = getGroupIdFromScopeId(
839                                            scopeId, scopeGroupId, layout.isPrivateLayout());
840    
841                                    i++;
842                            }
843                            catch (Exception e) {
844                                    continue;
845                            }
846                    }
847    
848                    return groupIds;
849            }
850    
851            @Override
852            public long getRecentFolderId(
853                    PortletRequest portletRequest, String className) {
854    
855                    Long classPK = _getRecentFolderIds(portletRequest).get(className);
856    
857                    if (classPK == null) {
858                            return 0;
859                    }
860                    else {
861                            return classPK.longValue();
862                    }
863            }
864    
865            @Override
866            public String getScopeId(Group group, long scopeGroupId)
867                    throws PortalException, SystemException {
868    
869                    String key = null;
870    
871                    if (group.isLayout()) {
872                            Layout layout = LayoutLocalServiceUtil.getLayout(
873                                    group.getClassPK());
874    
875                            key = SCOPE_ID_LAYOUT_UUID_PREFIX + layout.getUuid();
876                    }
877                    else if (group.isLayoutPrototype() ||
878                                     (group.getGroupId() == scopeGroupId)) {
879    
880                            key = SCOPE_ID_GROUP_PREFIX + GroupConstants.DEFAULT;
881                    }
882                    else {
883                            Group scopeGroup = GroupLocalServiceUtil.getGroup(scopeGroupId);
884    
885                            if (scopeGroup.hasAncestor(group.getGroupId())) {
886                                    key = SCOPE_ID_PARENT_GROUP_PREFIX + group.getGroupId();
887                            }
888                            else if (group.hasAncestor(scopeGroup.getGroupId())) {
889                                    key = SCOPE_ID_CHILD_GROUP_PREFIX + group.getGroupId();
890                            }
891                            else {
892                                    key = SCOPE_ID_GROUP_PREFIX + group.getGroupId();
893                            }
894                    }
895    
896                    return key;
897            }
898    
899            @Override
900            public boolean isScopeIdSelectable(
901                            PermissionChecker permissionChecker, String scopeId,
902                            long companyGroupId, Layout layout)
903                    throws PortalException, SystemException {
904    
905                    long groupId = getGroupIdFromScopeId(
906                            scopeId, layout.getGroupId(), layout.isPrivateLayout());
907    
908                    if (scopeId.startsWith(SCOPE_ID_CHILD_GROUP_PREFIX)) {
909                            Group group = GroupLocalServiceUtil.getGroup(groupId);
910    
911                            if (!group.hasAncestor(layout.getGroupId())) {
912                                    return false;
913                            }
914                    }
915                    else if (scopeId.startsWith(SCOPE_ID_PARENT_GROUP_PREFIX)) {
916                            Group siteGroup = layout.getGroup();
917    
918                            if (!siteGroup.hasAncestor(groupId)) {
919                                    return false;
920                            }
921    
922                            if (SitesUtil.isContentSharingWithChildrenEnabled(siteGroup)) {
923                                    return true;
924                            }
925    
926                            if (!PrefsPropsUtil.getBoolean(
927                                            layout.getCompanyId(),
928                                            PropsKeys.
929                                            SITES_CONTENT_SHARING_THROUGH_ADMINISTRATORS_ENABLED)) {
930    
931                                    return false;
932                            }
933    
934                            return GroupPermissionUtil.contains(
935                                    permissionChecker, groupId, ActionKeys.UPDATE);
936                    }
937                    else if (groupId != companyGroupId) {
938                            return GroupPermissionUtil.contains(
939                                    permissionChecker, groupId, ActionKeys.UPDATE);
940                    }
941    
942                    return true;
943            }
944    
945            @Override
946            public boolean isSubscribed(
947                            long companyId, long userId, long plid, String portletId)
948                    throws PortalException, SystemException {
949    
950                    return SubscriptionLocalServiceUtil.isSubscribed(
951                            companyId, userId,
952                            com.liferay.portal.model.PortletPreferences.class.getName(),
953                            _getPortletPreferencesId(plid, portletId));
954            }
955    
956            @Override
957            public void notifySubscribers(
958                            PortletPreferences preferences, long plid, String portletId,
959                            List<AssetEntry> assetEntries)
960                    throws PortalException, SystemException {
961    
962                    if (!getEmailAssetEntryAddedEnabled(preferences) ||
963                            assetEntries.isEmpty()) {
964    
965                            return;
966                    }
967    
968                    AssetEntry assetEntry = assetEntries.get(0);
969    
970                    String fromName = getEmailFromName(
971                            preferences, assetEntry.getCompanyId());
972                    String fromAddress = getEmailFromAddress(
973                            preferences, assetEntry.getCompanyId());
974    
975                    Map<Locale, String> localizedSubjectMap =
976                            getEmailAssetEntryAddedSubjectMap(preferences);
977                    Map<Locale, String> localizedBodyMap = getEmailAssetEntryAddedBodyMap(
978                            preferences);
979    
980                    SubscriptionSender subscriptionSender = new SubscriptionSender();
981    
982                    subscriptionSender.setCompanyId(assetEntry.getCompanyId());
983                    subscriptionSender.setContextAttributes(
984                            "[$ASSET_ENTRIES$]",
985                            ListUtil.toString(
986                                    assetEntries, _titleAccessor, StringPool.COMMA_AND_SPACE));
987                    subscriptionSender.setContextUserPrefix("ASSET_PUBLISHER");
988                    subscriptionSender.setFrom(fromAddress, fromName);
989                    subscriptionSender.setHtmlFormat(true);
990                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
991                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
992                    subscriptionSender.setMailId("asset_entry", assetEntry.getEntryId());
993                    subscriptionSender.setPortletId(PortletKeys.ASSET_PUBLISHER);
994                    subscriptionSender.setReplyToAddress(fromAddress);
995    
996                    subscriptionSender.addPersistedSubscribers(
997                            com.liferay.portal.model.PortletPreferences.class.getName(),
998                            _getPortletPreferencesId(plid, portletId));
999    
1000                    subscriptionSender.flushNotificationsAsync();
1001            }
1002    
1003            @Override
1004            public void removeAndStoreSelection(
1005                            List<String> assetEntryUuids, PortletPreferences portletPreferences)
1006                    throws Exception {
1007    
1008                    if (assetEntryUuids.size() == 0) {
1009                            return;
1010                    }
1011    
1012                    String[] assetEntryXmls = portletPreferences.getValues(
1013                            "assetEntryXml", new String[0]);
1014    
1015                    List<String> assetEntryXmlsList = ListUtil.fromArray(assetEntryXmls);
1016    
1017                    Iterator<String> itr = assetEntryXmlsList.iterator();
1018    
1019                    while (itr.hasNext()) {
1020                            String assetEntryXml = itr.next();
1021    
1022                            Document document = SAXReaderUtil.read(assetEntryXml);
1023    
1024                            Element rootElement = document.getRootElement();
1025    
1026                            String assetEntryUuid = rootElement.elementText("asset-entry-uuid");
1027    
1028                            if (assetEntryUuids.contains(assetEntryUuid)) {
1029                                    itr.remove();
1030                            }
1031                    }
1032    
1033                    portletPreferences.setValues(
1034                            "assetEntryXml",
1035                            assetEntryXmlsList.toArray(new String[assetEntryXmlsList.size()]));
1036    
1037                    portletPreferences.store();
1038            }
1039    
1040            @Override
1041            public void removeRecentFolderId(
1042                    PortletRequest portletRequest, String className, long classPK) {
1043    
1044                    if (getRecentFolderId(portletRequest, className) == classPK) {
1045                            _getRecentFolderIds(portletRequest).remove(className);
1046                    }
1047            }
1048    
1049            @Override
1050            public void subscribe(
1051                            PermissionChecker permissionChecker, long groupId, long plid,
1052                            String portletId)
1053                    throws PortalException, SystemException {
1054    
1055                    PortletPermissionUtil.check(
1056                            permissionChecker, plid, portletId, ActionKeys.SUBSCRIBE);
1057    
1058                    SubscriptionLocalServiceUtil.addSubscription(
1059                            permissionChecker.getUserId(), groupId,
1060                            com.liferay.portal.model.PortletPreferences.class.getName(),
1061                            _getPortletPreferencesId(plid, portletId));
1062            }
1063    
1064            @Override
1065            public void unsubscribe(
1066                            PermissionChecker permissionChecker, long plid, String portletId)
1067                    throws PortalException, SystemException {
1068    
1069                    PortletPermissionUtil.check(
1070                            permissionChecker, plid, portletId, ActionKeys.SUBSCRIBE);
1071    
1072                    SubscriptionLocalServiceUtil.deleteSubscription(
1073                            permissionChecker.getUserId(),
1074                            com.liferay.portal.model.PortletPreferences.class.getName(),
1075                            _getPortletPreferencesId(plid, portletId));
1076            }
1077    
1078            private void _checkAssetEntries(
1079                            com.liferay.portal.model.PortletPreferences portletPreferences)
1080                    throws PortalException, SystemException {
1081    
1082                    Layout layout = LayoutLocalServiceUtil.getLayout(
1083                            portletPreferences.getPlid());
1084    
1085                    PortletPreferences preferences = PortletPreferencesFactoryUtil.fromXML(
1086                            layout.getCompanyId(), portletPreferences.getOwnerId(),
1087                            portletPreferences.getOwnerType(), portletPreferences.getPlid(),
1088                            portletPreferences.getPortletId(),
1089                            portletPreferences.getPreferences());
1090    
1091                    if (!getEmailAssetEntryAddedEnabled(preferences)) {
1092                            return;
1093                    }
1094    
1095                    List<AssetEntry> assetEntries = getAssetEntries(
1096                            preferences, layout, layout.getGroupId(),
1097                            PropsValues.ASSET_PUBLISHER_DYNAMIC_SUBSCRIPTION_LIMIT, false);
1098    
1099                    if (assetEntries.isEmpty()) {
1100                            return;
1101                    }
1102    
1103                    long[] notifiedAssetEntryIds = GetterUtil.getLongValues(
1104                            preferences.getValues("notifiedAssetEntryIds", null));
1105    
1106                    List<AssetEntry> newAssetEntries = new ArrayList<AssetEntry>();
1107    
1108                    for (int i = 0; i < assetEntries.size(); i++) {
1109                            AssetEntry assetEntry = assetEntries.get(i);
1110    
1111                            if (!ArrayUtil.contains(
1112                                            notifiedAssetEntryIds, assetEntry.getEntryId())) {
1113    
1114                                    newAssetEntries.add(assetEntry);
1115                            }
1116                    }
1117    
1118                    notifySubscribers(
1119                            preferences, portletPreferences.getPlid(),
1120                            portletPreferences.getPortletId(), newAssetEntries);
1121    
1122                    try {
1123                            preferences.setValues(
1124                                    "notifiedAssetEntryIds",
1125                                    StringUtil.split(
1126                                            ListUtil.toString(
1127                                                    assetEntries, AssetEntry.ENTRY_ID_ACCESSOR)));
1128    
1129                            preferences.store();
1130                    }
1131                    catch (IOException ioe) {
1132                            throw new SystemException(ioe);
1133                    }
1134                    catch (PortletException pe) {
1135                            throw new SystemException(pe);
1136                    }
1137            }
1138    
1139            private String _getAssetEntryXml(
1140                    String assetEntryType, String assetEntryUuid) {
1141    
1142                    String xml = null;
1143    
1144                    try {
1145                            Document document = SAXReaderUtil.createDocument(StringPool.UTF8);
1146    
1147                            Element assetEntryElement = document.addElement("asset-entry");
1148    
1149                            Element assetEntryTypeElement = assetEntryElement.addElement(
1150                                    "asset-entry-type");
1151    
1152                            assetEntryTypeElement.addText(assetEntryType);
1153    
1154                            Element assetEntryUuidElement = assetEntryElement.addElement(
1155                                    "asset-entry-uuid");
1156    
1157                            assetEntryUuidElement.addText(assetEntryUuid);
1158    
1159                            xml = document.formattedString(StringPool.BLANK);
1160                    }
1161                    catch (IOException ioe) {
1162                            if (_log.isWarnEnabled()) {
1163                                    _log.warn(ioe);
1164                            }
1165                    }
1166    
1167                    return xml;
1168            }
1169    
1170            private long _getPortletPreferencesId(long plid, String portletId)
1171                    throws PortalException, SystemException {
1172    
1173                    com.liferay.portal.model.PortletPreferences portletPreferences =
1174                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
1175                                    PortletKeys.PREFS_OWNER_ID_DEFAULT,
1176                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, plid, portletId);
1177    
1178                    return portletPreferences.getPortletPreferencesId();
1179            }
1180    
1181            private Map<String, Long> _getRecentFolderIds(
1182                    PortletRequest portletRequest) {
1183    
1184                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
1185                            portletRequest);
1186                    HttpSession session = request.getSession();
1187    
1188                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1189                            WebKeys.THEME_DISPLAY);
1190    
1191                    String key =
1192                            AssetPublisherUtil.class + StringPool.UNDERLINE +
1193                                    themeDisplay.getScopeGroupId();
1194    
1195                    Map<String, Long> recentFolderIds =
1196                            (Map<String, Long>)session.getAttribute(key);
1197    
1198                    if (recentFolderIds == null) {
1199                            recentFolderIds = new HashMap<String, Long>();
1200                    }
1201    
1202                    session.setAttribute(key, recentFolderIds);
1203    
1204                    return recentFolderIds;
1205            }
1206    
1207            private static Log _log = LogFactoryUtil.getLog(AssetPublisherImpl.class);
1208    
1209            private Accessor<AssetEntry, String> _titleAccessor =
1210                    new Accessor<AssetEntry, String>() {
1211    
1212                            @Override
1213                            public String get(AssetEntry assetEntry) {
1214                                    return assetEntry.getTitle(LocaleUtil.getSiteDefault());
1215                            }
1216    
1217                    };
1218    
1219    }