001    /**
002     * Copyright (c) 2000-2010 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.imagegallery.lar;
016    
017    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.StringBundler;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.xml.Document;
028    import com.liferay.portal.kernel.xml.Element;
029    import com.liferay.portal.kernel.xml.SAXReaderUtil;
030    import com.liferay.portal.model.Image;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portal.service.persistence.ImageUtil;
033    import com.liferay.portal.util.PortletKeys;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.imagegallery.DuplicateImageNameException;
036    import com.liferay.portlet.imagegallery.model.IGFolder;
037    import com.liferay.portlet.imagegallery.model.IGFolderConstants;
038    import com.liferay.portlet.imagegallery.model.IGImage;
039    import com.liferay.portlet.imagegallery.service.IGFolderLocalServiceUtil;
040    import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
041    import com.liferay.portlet.imagegallery.service.persistence.IGFolderUtil;
042    import com.liferay.portlet.imagegallery.service.persistence.IGImageUtil;
043    import com.liferay.util.PwdGenerator;
044    
045    import java.io.File;
046    
047    import java.util.List;
048    import java.util.Map;
049    import java.util.regex.Pattern;
050    
051    import javax.portlet.PortletPreferences;
052    
053    /**
054     * @author Bruno Farache
055     * @author Raymond Augé
056     * @author Juan Fernández
057     */
058    public class IGPortletDataHandlerImpl extends BasePortletDataHandler {
059    
060            public static void exportImage(
061                            PortletDataContext context, Element foldersElement,
062                            Element imagesElement, IGImage image)
063                    throws Exception {
064    
065                    if (!context.isWithinDateRange(image.getModifiedDate())) {
066                            return;
067                    }
068    
069                    if (foldersElement != null) {
070                            exportParentFolder(context, foldersElement, image.getFolderId());
071                    }
072    
073                    String path = getImagePath(context, image);
074    
075                    if (context.isPathNotProcessed(path)) {
076                            Element imageElement = imagesElement.addElement("image");
077    
078                            imageElement.addAttribute("path", path);
079                            imageElement.addAttribute(
080                                    "bin-path", getImageBinPath(context, image));
081    
082                            if (context.getBooleanParameter(_NAMESPACE, "categories")) {
083                                    context.addAssetCategories(IGImage.class, image.getImageId());
084                            }
085    
086                            if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
087                                    context.addRatingsEntries(IGImage.class, image.getImageId());
088                            }
089    
090                            if (context.getBooleanParameter(_NAMESPACE, "tags")) {
091                                    context.addAssetTags(IGImage.class, image.getImageId());
092                            }
093    
094                            image.setUserUuid(image.getUserUuid());
095    
096                            Image largeImage = ImageUtil.findByPrimaryKey(
097                                    image.getLargeImageId());
098    
099                            image.setImageType(largeImage.getType());
100    
101                            context.addPermissions(IGImage.class, image.getImageId());
102    
103                            context.addZipEntry(
104                                    getImageBinPath(context, image), largeImage.getTextObj());
105    
106                            context.addZipEntry(path, image);
107                    }
108            }
109    
110            public static String getImagePath(
111                    PortletDataContext context, IGImage image) {
112    
113                    StringBundler sb = new StringBundler(4);
114    
115                    sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
116                    sb.append("/images/");
117                    sb.append(image.getImageId());
118                    sb.append(".xml");
119    
120                    return sb.toString();
121            }
122    
123            public static void importFolder(
124                            PortletDataContext context, Element folderElement)
125                    throws Exception {
126    
127                    String path = folderElement.attributeValue("path");
128    
129                    if (!context.isPathNotProcessed(path)) {
130                            return;
131                    }
132    
133                    IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
134    
135                    importFolder(context, folder);
136            }
137    
138            public static void importImage(
139                            PortletDataContext context, Element imageElement)
140                    throws Exception {
141    
142                    String path = imageElement.attributeValue("path");
143    
144                    String binPath = imageElement.attributeValue("bin-path");
145    
146                    if (!context.isPathNotProcessed(path)) {
147                            return;
148                    }
149    
150                    IGImage image = (IGImage)context.getZipEntryAsObject(path);
151    
152                    importImage(context, image, binPath);
153            }
154    
155            public PortletDataHandlerControl[] getExportControls() {
156                    return new PortletDataHandlerControl[] {
157                            _foldersAndImages, _categories, _ratings, _tags
158                    };
159            }
160    
161            public PortletDataHandlerControl[] getImportControls() {
162                    return new PortletDataHandlerControl[] {
163                            _foldersAndImages, _categories, _ratings, _tags
164                    };
165            }
166    
167            public boolean isAlwaysExportable() {
168                    return _ALWAYS_EXPORTABLE;
169            }
170    
171            public boolean isPublishToLiveByDefault() {
172                    return PropsValues.DL_PUBLISH_TO_LIVE_BY_DEFAULT;
173            }
174    
175            protected static void importFolder(
176                            PortletDataContext context, IGFolder folder)
177                    throws Exception {
178    
179                    long userId = context.getUserId(folder.getUserUuid());
180    
181                    Map<Long, Long> folderPKs =
182                            (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
183    
184                    long parentFolderId = MapUtil.getLong(
185                            folderPKs, folder.getParentFolderId(), folder.getParentFolderId());
186    
187                    ServiceContext serviceContext = new ServiceContext();
188    
189                    serviceContext.setAddCommunityPermissions(true);
190                    serviceContext.setAddGuestPermissions(true);
191                    serviceContext.setCreateDate(folder.getCreateDate());
192                    serviceContext.setModifiedDate(folder.getModifiedDate());
193                    serviceContext.setScopeGroupId(context.getScopeGroupId());
194    
195                    if ((parentFolderId != IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
196                            (parentFolderId == folder.getParentFolderId())) {
197    
198                            String path = getImportFolderPath(context, parentFolderId);
199    
200                            IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
201    
202                            importFolder(context, parentFolder);
203    
204                            parentFolderId = MapUtil.getLong(
205                                    folderPKs, folder.getParentFolderId(),
206                                    folder.getParentFolderId());
207                    }
208    
209                    IGFolder importedFolder = null;
210    
211                    if (context.isDataStrategyMirror()) {
212                            IGFolder existingFolder = IGFolderUtil.fetchByUUID_G(
213                                    folder.getUuid(), context.getScopeGroupId());
214    
215                            if (existingFolder == null) {
216                                    String name = getFolderName(
217                                            context.getCompanyId(), context.getScopeGroupId(),
218                                            parentFolderId, folder.getName(), 2);
219    
220                                    serviceContext.setUuid(folder.getUuid());
221    
222                                    importedFolder = IGFolderLocalServiceUtil.addFolder(
223                                            userId, parentFolderId, name, folder.getDescription(),
224                                            serviceContext);
225                            }
226                            else {
227                                    importedFolder = IGFolderLocalServiceUtil.updateFolder(
228                                            existingFolder.getFolderId(), parentFolderId,
229                                            folder.getName(), folder.getDescription(), false,
230                                            serviceContext);
231                            }
232                    }
233                    else {
234                            String name = getFolderName(
235                                    context.getCompanyId(), context.getScopeGroupId(),
236                                    parentFolderId, folder.getName(), 2);
237    
238                            importedFolder = IGFolderLocalServiceUtil.addFolder(
239                                    userId, parentFolderId, name, folder.getDescription(),
240                                    serviceContext);
241                    }
242    
243                    folderPKs.put(folder.getFolderId(), importedFolder.getFolderId());
244    
245                    context.importPermissions(
246                            IGFolder.class, folder.getFolderId(), importedFolder.getFolderId());
247            }
248    
249            protected static void importImage(
250                            PortletDataContext context, IGImage image, String binPath)
251                    throws Exception {
252    
253                    long userId = context.getUserId(image.getUserUuid());
254    
255                    Map<Long, Long> folderPKs =
256                            (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
257    
258                    long folderId = MapUtil.getLong(
259                            folderPKs, image.getFolderId(), image.getFolderId());
260    
261                    File imageFile = null;
262    
263                    byte[] bytes = context.getZipEntryAsByteArray(binPath);
264    
265                    if (bytes == null) {
266                            _log.error(
267                                    "Could not find image file for image " + image.getImageId());
268    
269                            return;
270                    }
271                    else {
272                            imageFile = File.createTempFile(
273                                    String.valueOf(image.getPrimaryKey()),
274                                    StringPool.PERIOD + image.getImageType());
275    
276                            FileUtil.write(imageFile, bytes);
277                    }
278    
279                    long[] assetCategoryIds = null;
280                    String[] assetTagNames = null;
281    
282                    if (context.getBooleanParameter(_NAMESPACE, "categories")) {
283                            assetCategoryIds = context.getAssetCategoryIds(
284                                    IGImage.class, image.getImageId());
285                    }
286    
287                    if (context.getBooleanParameter(_NAMESPACE, "tags")) {
288                            assetTagNames = context.getAssetTagNames(
289                                    IGImage.class, image.getImageId());
290                    }
291    
292                    ServiceContext serviceContext = new ServiceContext();
293    
294                    serviceContext.setAddCommunityPermissions(true);
295                    serviceContext.setAddGuestPermissions(true);
296                    serviceContext.setAssetCategoryIds(assetCategoryIds);
297                    serviceContext.setAssetTagNames(assetTagNames);
298                    serviceContext.setCreateDate(image.getCreateDate());
299                    serviceContext.setModifiedDate(image.getModifiedDate());
300    
301                    if ((folderId != IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
302                            (folderId == image.getFolderId())) {
303    
304                            String path = getImportFolderPath(context, folderId);
305    
306                            IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
307    
308                            importFolder(context, folder);
309    
310                            folderId = MapUtil.getLong(
311                                    folderPKs, image.getFolderId(), image.getFolderId());
312                    }
313    
314                    IGImage importedImage = null;
315    
316                    if (context.isDataStrategyMirror()) {
317                            IGImage existingImage = IGImageUtil.fetchByUUID_G(
318                                    image.getUuid(), context.getScopeGroupId());
319    
320                            if (existingImage == null) {
321                                    serviceContext.setUuid(image.getUuid());
322    
323                                    importedImage = IGImageLocalServiceUtil.addImage(
324                                            userId, context.getScopeGroupId(), folderId,
325                                            image.getName(), image.getDescription(), imageFile,
326                                            image.getImageType(), serviceContext);
327                            }
328                            else {
329                                    importedImage = IGImageLocalServiceUtil.updateImage(
330                                            userId, existingImage.getImageId(),
331                                            context.getScopeGroupId(), folderId, image.getName(),
332                                            image.getDescription(), imageFile, image.getImageType(),
333                                            serviceContext);
334                            }
335                    }
336                    else {
337                            String name = image.getName();
338    
339                            try {
340                                    importedImage = IGImageLocalServiceUtil.addImage(
341                                            userId, context.getScopeGroupId(), folderId, name,
342                                            image.getDescription(), imageFile, image.getImageType(),
343                                            serviceContext);
344                            }
345                            catch (DuplicateImageNameException dine) {
346                                    String[] nameParts = name.split("\\.", 2);
347    
348                                    name = nameParts[0] + PwdGenerator.getPassword();
349    
350                                    if (nameParts.length > 1) {
351                                            name += StringPool.PERIOD + nameParts[1];
352                                    }
353    
354                                    importedImage = IGImageLocalServiceUtil.addImage(
355                                            userId, context.getScopeGroupId(), folderId, name,
356                                            image.getDescription(), imageFile, image.getImageType(),
357                                            serviceContext);
358                            }
359                    }
360    
361                    context.importPermissions(
362                            IGImage.class, image.getImageId(), importedImage.getImageId());
363    
364                    if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
365                            context.importRatingsEntries(
366                                    IGImage.class, image.getImageId(), importedImage.getImageId());
367                    }
368    
369                    Map<Long, Long> igImagePKs =
370                            (Map<Long, Long>)context.getNewPrimaryKeysMap(IGImage.class);
371    
372                    igImagePKs.put(image.getImageId(), importedImage.getImageId());
373            }
374    
375            protected static void exportFolder(
376                            PortletDataContext context, Element foldersElement,
377                            Element imagesElement, IGFolder folder)
378                    throws Exception {
379    
380                    if (context.isWithinDateRange(folder.getModifiedDate())) {
381                            exportParentFolder(
382                                    context, foldersElement, folder.getParentFolderId());
383    
384                            String path = getFolderPath(context, folder.getFolderId());
385    
386                            if (context.isPathNotProcessed(path)) {
387                                    Element folderElement = foldersElement.addElement("folder");
388    
389                                    folderElement.addAttribute("path", path);
390    
391                                    folder.setUserUuid(folder.getUserUuid());
392    
393                                    context.addPermissions(IGFolder.class, folder.getFolderId());
394    
395                                    context.addZipEntry(path, folder);
396                            }
397                    }
398    
399                    List<IGImage> images = IGImageUtil.findByG_F(
400                            folder.getGroupId(), folder.getFolderId());
401    
402                    for (IGImage image : images) {
403                            exportImage(context, foldersElement, imagesElement, image);
404                    }
405            }
406    
407            protected static void exportParentFolder(
408                            PortletDataContext context, Element foldersElement, long folderId)
409                    throws Exception {
410    
411                    if (folderId == IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
412                            return;
413                    }
414    
415                    IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
416    
417                    exportParentFolder(context, foldersElement, folder.getParentFolderId());
418    
419                    String path = getFolderPath(context, folder.getFolderId());
420    
421                    if (context.isPathNotProcessed(path)) {
422                            Element folderElement = foldersElement.addElement("folder");
423    
424                            folderElement.addAttribute("path", path);
425    
426                            folder.setUserUuid(folder.getUserUuid());
427    
428                            context.addPermissions(IGFolder.class, folder.getFolderId());
429    
430                            context.addZipEntry(path, folder);
431                    }
432            }
433    
434            protected static String getFolderName(
435                            long companyId, long groupId, long parentFolderId, String name,
436                            int count)
437                    throws Exception {
438    
439                    IGFolder folder = IGFolderUtil.fetchByG_P_N(
440                            groupId, parentFolderId, name);
441    
442                    if (folder == null) {
443                            return name;
444                    }
445    
446                    if (Pattern.matches(".* \\(\\d+\\)", name)) {
447                            int pos = name.lastIndexOf(" (");
448    
449                            name = name.substring(0, pos);
450                    }
451    
452                    StringBundler sb = new StringBundler(5);
453    
454                    sb.append(name);
455                    sb.append(StringPool.SPACE);
456                    sb.append(StringPool.OPEN_PARENTHESIS);
457                    sb.append(count);
458                    sb.append(StringPool.CLOSE_PARENTHESIS);
459    
460                    name = sb.toString();
461    
462                    return getFolderName(companyId, groupId, parentFolderId, name, ++count);
463            }
464    
465            protected static String getFolderPath(
466                    PortletDataContext context, long folderId) {
467    
468                    StringBundler sb = new StringBundler(4);
469    
470                    sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
471                    sb.append("/folders/");
472                    sb.append(folderId);
473                    sb.append(".xml");
474    
475                    return sb.toString();
476            }
477    
478            protected static String getImageBinPath(
479                    PortletDataContext context, IGImage image) {
480    
481                    StringBundler sb = new StringBundler(5);
482    
483                    sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
484                    sb.append("/bin/");
485                    sb.append(image.getImageId());
486                    sb.append(StringPool.PERIOD);
487                    sb.append(image.getImageType());
488    
489                    return sb.toString();
490            }
491    
492            protected static String getImportFolderPath(
493                    PortletDataContext context, long folderId) {
494    
495                    StringBundler sb = new StringBundler(4);
496    
497                    sb.append(context.getSourcePortletPath(PortletKeys.IMAGE_GALLERY));
498                    sb.append("/folders/");
499                    sb.append(folderId);
500                    sb.append(".xml");
501    
502                    return sb.toString();
503            }
504    
505            protected PortletPreferences doDeleteData(
506                            PortletDataContext context, String portletId,
507                            PortletPreferences preferences)
508                    throws Exception {
509    
510                    if (!context.addPrimaryKey(
511                                    IGPortletDataHandlerImpl.class, "deleteData")) {
512    
513                            IGFolderLocalServiceUtil.deleteFolders(context.getScopeGroupId());
514    
515                            IGImageLocalServiceUtil.deleteImages(
516                                    context.getScopeGroupId(),
517                                    IGFolderConstants.DEFAULT_PARENT_FOLDER_ID);
518                    }
519    
520                    return null;
521            }
522    
523            protected String doExportData(
524                            PortletDataContext context, String portletId,
525                            PortletPreferences preferences)
526                    throws Exception {
527    
528                    context.addPermissions(
529                            "com.liferay.portlet.imagegallery", context.getScopeGroupId());
530    
531                    Document document = SAXReaderUtil.createDocument();
532    
533                    Element rootElement = document.addElement("image-gallery");
534    
535                    rootElement.addAttribute(
536                            "group-id", String.valueOf(context.getScopeGroupId()));
537    
538                    Element foldersElement = rootElement.addElement("folders");
539                    Element imagesElement = rootElement.addElement("images");
540    
541                    List<IGFolder> folders = IGFolderUtil.findByGroupId(
542                            context.getScopeGroupId());
543    
544                    for (IGFolder folder : folders) {
545                            exportFolder(context, foldersElement, imagesElement, folder);
546                    }
547    
548                    List<IGImage> images = IGImageUtil.findByG_F(
549                            context.getScopeGroupId(),
550                            IGFolderConstants.DEFAULT_PARENT_FOLDER_ID);
551    
552                    for (IGImage image : images) {
553                            exportImage(context, null, imagesElement, image);
554                    }
555    
556                    return document.formattedString();
557            }
558    
559            protected PortletPreferences doImportData(
560                            PortletDataContext context, String portletId,
561                            PortletPreferences preferences, String data)
562                    throws Exception {
563    
564                    context.importPermissions(
565                            "com.liferay.portlet.imagegallery",
566                            context.getSourceGroupId(), context.getScopeGroupId());
567    
568                    Document document = SAXReaderUtil.read(data);
569    
570                    Element rootElement = document.getRootElement();
571    
572                    Element foldersElement = rootElement.element("folders");
573    
574                    List<Element> folderElements = foldersElement.elements("folder");
575    
576                    for (Element folderElement : folderElements) {
577                            String path = folderElement.attributeValue("path");
578    
579                            if (!context.isPathNotProcessed(path)) {
580                                    continue;
581                            }
582    
583                            IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
584    
585                            importFolder(context, folder);
586                    }
587    
588                    Element imagesElement = rootElement.element("images");
589    
590                    List<Element> imageElements = imagesElement.elements("image");
591    
592                    for (Element imageElement : imageElements) {
593                            String path = imageElement.attributeValue("path");
594    
595                            if (!context.isPathNotProcessed(path)) {
596                                    continue;
597                            }
598    
599                            IGImage image = (IGImage)context.getZipEntryAsObject(path);
600    
601                            String binPath = imageElement.attributeValue("bin-path");
602    
603                            importImage(context, image, binPath);
604                    }
605    
606                    return null;
607            }
608    
609            private static final boolean _ALWAYS_EXPORTABLE = true;
610    
611            private static final String _NAMESPACE = "image_gallery";
612    
613            private static Log _log = LogFactoryUtil.getLog(
614                    IGPortletDataHandlerImpl.class);
615    
616            private static PortletDataHandlerBoolean _categories =
617                    new PortletDataHandlerBoolean(_NAMESPACE, "categories");
618    
619            private static PortletDataHandlerBoolean _foldersAndImages =
620                    new PortletDataHandlerBoolean(
621                            _NAMESPACE, "folders-and-images", true, true);
622    
623            private static PortletDataHandlerBoolean _ratings =
624                    new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
625    
626            private static PortletDataHandlerBoolean _tags =
627                    new PortletDataHandlerBoolean(_NAMESPACE, "tags");
628    
629    }