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