1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.imagegallery.lar;
16  
17  import com.liferay.portal.kernel.exception.PortalException;
18  import com.liferay.portal.kernel.exception.SystemException;
19  import com.liferay.portal.kernel.lar.BasePortletDataHandler;
20  import com.liferay.portal.kernel.lar.PortletDataContext;
21  import com.liferay.portal.kernel.lar.PortletDataException;
22  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
23  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
24  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.FileUtil;
28  import com.liferay.portal.kernel.util.MapUtil;
29  import com.liferay.portal.kernel.util.StringBundler;
30  import com.liferay.portal.kernel.util.StringPool;
31  import com.liferay.portal.kernel.xml.Document;
32  import com.liferay.portal.kernel.xml.Element;
33  import com.liferay.portal.kernel.xml.SAXReaderUtil;
34  import com.liferay.portal.model.Image;
35  import com.liferay.portal.service.ServiceContext;
36  import com.liferay.portal.service.persistence.ImageUtil;
37  import com.liferay.portal.util.PortletKeys;
38  import com.liferay.portlet.imagegallery.NoSuchFolderException;
39  import com.liferay.portlet.imagegallery.model.IGFolder;
40  import com.liferay.portlet.imagegallery.model.IGFolderConstants;
41  import com.liferay.portlet.imagegallery.model.IGImage;
42  import com.liferay.portlet.imagegallery.service.IGFolderLocalServiceUtil;
43  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
44  import com.liferay.portlet.imagegallery.service.persistence.IGFolderUtil;
45  import com.liferay.portlet.imagegallery.service.persistence.IGImageUtil;
46  
47  import java.io.File;
48  
49  import java.util.List;
50  import java.util.Map;
51  import java.util.regex.Pattern;
52  
53  import javax.portlet.PortletPreferences;
54  
55  /**
56   * <a href="IGPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
57   *
58   * @author Bruno Farache
59   * @author Raymond Augé
60   * @author Juan Fernández
61   */
62  public class IGPortletDataHandlerImpl extends BasePortletDataHandler {
63  
64      public static void exportImage(
65              PortletDataContext context, Element foldersEl, Element imagesEl,
66              IGImage image)
67          throws PortalException, SystemException {
68  
69          if (!context.isWithinDateRange(image.getModifiedDate())) {
70              return;
71          }
72  
73          if (foldersEl != null) {
74              exportParentFolder(context, foldersEl, image.getFolderId());
75          }
76  
77          String path = getImagePath(context, image);
78  
79          if (context.isPathNotProcessed(path)) {
80              Element imageEl = imagesEl.addElement("image");
81  
82              imageEl.addAttribute("path", path);
83              imageEl.addAttribute("bin-path", getImageBinPath(context, image));
84  
85              if (context.getBooleanParameter(_NAMESPACE, "categories")) {
86                  context.addAssetCategories(IGImage.class, image.getImageId());
87              }
88  
89              if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
90                  context.addRatingsEntries(IGImage.class, image.getImageId());
91              }
92  
93              if (context.getBooleanParameter(_NAMESPACE, "tags")) {
94                  context.addAssetTags(IGImage.class, image.getImageId());
95              }
96  
97              image.setUserUuid(image.getUserUuid());
98  
99              Image largeImage = ImageUtil.findByPrimaryKey(
100                 image.getLargeImageId());
101 
102             image.setImageType(largeImage.getType());
103 
104             context.addPermissions(IGImage.class, image.getImageId());
105 
106             context.addZipEntry(
107                 getImageBinPath(context, image), largeImage.getTextObj());
108 
109             context.addZipEntry(path, image);
110         }
111     }
112 
113     public static void importFolder(
114             PortletDataContext context, Map<Long, Long> folderPKs,
115             IGFolder folder)
116         throws Exception {
117 
118         long userId = context.getUserId(folder.getUserUuid());
119         long parentFolderId = MapUtil.getLong(
120             folderPKs, folder.getParentFolderId(), folder.getParentFolderId());
121 
122         ServiceContext serviceContext = new ServiceContext();
123 
124         serviceContext.setAddCommunityPermissions(true);
125         serviceContext.setAddGuestPermissions(true);
126         serviceContext.setCreateDate(folder.getCreateDate());
127         serviceContext.setModifiedDate(folder.getModifiedDate());
128         serviceContext.setScopeGroupId(context.getGroupId());
129 
130         if ((parentFolderId != IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
131             (parentFolderId == folder.getParentFolderId())) {
132 
133             String path = getImportFolderPath(context, parentFolderId);
134 
135             IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
136 
137             importFolder(context, folderPKs, parentFolder);
138 
139             parentFolderId = MapUtil.getLong(
140                 folderPKs, folder.getParentFolderId(),
141                 folder.getParentFolderId());
142         }
143 
144         IGFolder importedFolder = null;
145 
146         try {
147             if (parentFolderId != IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
148                 IGFolderUtil.findByPrimaryKey(parentFolderId);
149             }
150 
151             if (context.getDataStrategy().equals(
152                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
153 
154                 IGFolder existingFolder = IGFolderUtil.fetchByUUID_G(
155                     folder.getUuid(), context.getGroupId());
156 
157                 if (existingFolder == null) {
158                     String name = getFolderName(
159                         context.getCompanyId(), context.getGroupId(),
160                         parentFolderId, folder.getName(), 2);
161 
162                     importedFolder = IGFolderLocalServiceUtil.addFolder(
163                         folder.getUuid(), userId, parentFolderId, name,
164                         folder.getDescription(), serviceContext);
165                 }
166                 else {
167                     importedFolder = IGFolderLocalServiceUtil.updateFolder(
168                         existingFolder.getFolderId(), parentFolderId,
169                         folder.getName(), folder.getDescription(), false,
170                         serviceContext);
171                 }
172             }
173             else {
174                 String name = getFolderName(
175                     context.getCompanyId(), context.getGroupId(),
176                     parentFolderId, folder.getName(), 2);
177 
178                 importedFolder = IGFolderLocalServiceUtil.addFolder(
179                     null, userId, parentFolderId, name, folder.getDescription(),
180                     serviceContext);
181             }
182 
183             folderPKs.put(folder.getFolderId(), importedFolder.getFolderId());
184 
185             context.importPermissions(
186                 IGFolder.class, folder.getFolderId(),
187                 importedFolder.getFolderId());
188         }
189         catch (NoSuchFolderException nsfe) {
190             _log.error(
191                 "Could not find the parent folder for folder " +
192                     folder.getFolderId());
193         }
194     }
195 
196     public static void importImage(
197             PortletDataContext context, Map<Long, Long> folderPKs,
198             IGImage image, String binPath)
199         throws Exception {
200 
201         long userId = context.getUserId(image.getUserUuid());
202         long groupId = context.getGroupId();
203         long folderId = MapUtil.getLong(
204             folderPKs, image.getFolderId(), image.getFolderId());
205 
206         File imageFile = null;
207 
208         byte[] bytes = context.getZipEntryAsByteArray(binPath);
209 
210         if (bytes == null) {
211             _log.error(
212                 "Could not find image file for image " + image.getImageId());
213 
214             return;
215         }
216         else {
217             imageFile = File.createTempFile(
218                 String.valueOf(image.getPrimaryKey()),
219                 StringPool.PERIOD + image.getImageType());
220 
221             FileUtil.write(imageFile, bytes);
222         }
223 
224         long[] assetCategoryIds = null;
225         String[] assetTagNames = null;
226 
227         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
228             assetCategoryIds = context.getAssetCategoryIds(
229                 IGImage.class, image.getImageId());
230         }
231 
232         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
233             assetTagNames = context.getAssetTagNames(
234                 IGImage.class, image.getImageId());
235         }
236 
237         ServiceContext serviceContext = new ServiceContext();
238 
239         serviceContext.setAddCommunityPermissions(true);
240         serviceContext.setAddGuestPermissions(true);
241         serviceContext.setAssetCategoryIds(assetCategoryIds);
242         serviceContext.setAssetTagNames(assetTagNames);
243         serviceContext.setCreateDate(image.getCreateDate());
244         serviceContext.setModifiedDate(image.getModifiedDate());
245 
246         if ((folderId != IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) &&
247             (folderId == image.getFolderId())) {
248 
249             String path = getImportFolderPath(context, folderId);
250 
251             IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
252 
253             importFolder(context, folderPKs, folder);
254 
255             folderId = MapUtil.getLong(
256                 folderPKs, image.getFolderId(), image.getFolderId());
257         }
258 
259         IGImage importedImage = null;
260 
261         try {
262             if (context.getDataStrategy().equals(
263                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
264 
265                 IGImage existingImage = IGImageUtil.fetchByUUID_G(
266                     image.getUuid(), groupId);
267 
268                 if (existingImage == null) {
269                     importedImage = IGImageLocalServiceUtil.addImage(
270                         image.getUuid(), userId, groupId, folderId,
271                         image.getName(), image.getDescription(), imageFile,
272                         image.getImageType(), serviceContext);
273                 }
274                 else {
275                     importedImage = IGImageLocalServiceUtil.updateImage(
276                         userId, existingImage.getImageId(), groupId, folderId,
277                         image.getName(), image.getDescription(), imageFile,
278                         image.getImageType(), serviceContext);
279                 }
280             }
281             else {
282                 importedImage = IGImageLocalServiceUtil.addImage(
283                     null, userId, groupId, folderId, image.getName(),
284                     image.getDescription(), imageFile, image.getImageType(),
285                     serviceContext);
286             }
287 
288             context.importPermissions(
289                 IGImage.class, image.getImageId(), importedImage.getImageId());
290 
291             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
292                 context.importRatingsEntries(
293                     IGImage.class, image.getImageId(),
294                     importedImage.getImageId());
295             }
296         }
297         catch (NoSuchFolderException nsfe) {
298             _log.error(
299                 "Could not find the parent folder for image " +
300                     image.getImageId());
301         }
302     }
303 
304     public PortletPreferences deleteData(
305             PortletDataContext context, String portletId,
306             PortletPreferences preferences)
307         throws PortletDataException {
308 
309         try {
310             if (!context.addPrimaryKey(
311                     IGPortletDataHandlerImpl.class, "deleteData")) {
312 
313                 IGFolderLocalServiceUtil.deleteFolders(context.getGroupId());
314             }
315 
316             return null;
317         }
318         catch (Exception e) {
319             throw new PortletDataException(e);
320         }
321     }
322 
323     public String exportData(
324             PortletDataContext context, String portletId,
325             PortletPreferences preferences)
326         throws PortletDataException {
327 
328         try {
329             context.addPermissions(
330                 "com.liferay.portlet.imagegallery", context.getGroupId());
331 
332             Document doc = SAXReaderUtil.createDocument();
333 
334             Element root = doc.addElement("image-gallery");
335 
336             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
337 
338             Element foldersEl = root.addElement("folders");
339             Element imagesEl = root.addElement("images");
340 
341             List<IGFolder> folders = IGFolderUtil.findByGroupId(
342                 context.getGroupId());
343 
344             for (IGFolder folder : folders) {
345                 exportFolder(context, foldersEl, imagesEl, folder);
346             }
347 
348             List<IGImage> images = IGImageUtil.findByG_F(
349                 context.getGroupId(),
350                 IGFolderConstants.DEFAULT_PARENT_FOLDER_ID);
351 
352             for (IGImage image : images) {
353                 exportImage(context, null, imagesEl, image);
354             }
355 
356             return doc.formattedString();
357         }
358         catch (Exception e) {
359             throw new PortletDataException(e);
360         }
361     }
362 
363     public PortletDataHandlerControl[] getExportControls() {
364         return new PortletDataHandlerControl[] {
365             _foldersAndImages, _categories, _ratings, _tags
366         };
367     }
368 
369     public PortletDataHandlerControl[] getImportControls() {
370         return new PortletDataHandlerControl[] {
371             _foldersAndImages, _categories, _ratings, _tags
372         };
373     }
374 
375     public PortletPreferences importData(
376             PortletDataContext context, String portletId,
377             PortletPreferences preferences, String data)
378         throws PortletDataException {
379 
380         try {
381             context.importPermissions(
382                 "com.liferay.portlet.imagegallery",
383                 context.getSourceGroupId(), context.getGroupId());
384 
385             Document doc = SAXReaderUtil.read(data);
386 
387             Element root = doc.getRootElement();
388 
389             List<Element> folderEls = root.element("folders").elements(
390                 "folder");
391 
392             Map<Long, Long> folderPKs =
393                 (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
394 
395             for (Element folderEl : folderEls) {
396                 String path = folderEl.attributeValue("path");
397 
398                 if (!context.isPathNotProcessed(path)) {
399                     continue;
400                 }
401 
402                 IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
403 
404                 importFolder(context, folderPKs, folder);
405             }
406 
407             List<Element> imageEls = root.element("images").elements("image");
408 
409             for (Element imageEl : imageEls) {
410                 String path = imageEl.attributeValue("path");
411 
412                 if (!context.isPathNotProcessed(path)) {
413                     continue;
414                 }
415 
416                 IGImage image = (IGImage)context.getZipEntryAsObject(path);
417 
418                 String binPath = imageEl.attributeValue("bin-path");
419 
420                 importImage(context, folderPKs, image, binPath);
421             }
422 
423             return null;
424         }
425         catch (Exception e) {
426             throw new PortletDataException(e);
427         }
428     }
429 
430     protected static void exportFolder(
431             PortletDataContext context, Element foldersEl, Element imagesEl,
432             IGFolder folder)
433         throws PortalException, SystemException {
434 
435         if (context.isWithinDateRange(folder.getModifiedDate())) {
436             exportParentFolder(context, foldersEl, folder.getParentFolderId());
437 
438             String path = getFolderPath(context, folder.getFolderId());
439 
440             if (context.isPathNotProcessed(path)) {
441                 Element folderEl = foldersEl.addElement("folder");
442 
443                 folderEl.addAttribute("path", path);
444 
445                 folder.setUserUuid(folder.getUserUuid());
446 
447                 context.addPermissions(IGFolder.class, folder.getFolderId());
448 
449                 context.addZipEntry(path, folder);
450             }
451         }
452 
453         List<IGImage> images = IGImageUtil.findByG_F(
454             folder.getGroupId(), folder.getFolderId());
455 
456         for (IGImage image : images) {
457             exportImage(context, foldersEl, imagesEl, image);
458         }
459     }
460 
461     protected static void exportParentFolder(
462             PortletDataContext context, Element foldersEl, long folderId)
463         throws PortalException, SystemException {
464 
465         if (folderId == IGFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
466             return;
467         }
468 
469         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
470 
471         exportParentFolder(context, foldersEl, folder.getParentFolderId());
472 
473         String path = getFolderPath(context, folder.getFolderId());
474 
475         if (context.isPathNotProcessed(path)) {
476             Element folderEl = foldersEl.addElement("folder");
477 
478             folderEl.addAttribute("path", path);
479 
480             folder.setUserUuid(folder.getUserUuid());
481 
482             context.addPermissions(IGFolder.class, folder.getFolderId());
483 
484             context.addZipEntry(path, folder);
485         }
486     }
487 
488     protected static String getFolderName(
489             long companyId, long groupId, long parentFolderId, String name,
490             int count)
491         throws SystemException {
492 
493         IGFolder folder = IGFolderUtil.fetchByG_P_N(
494             groupId, parentFolderId, name);
495 
496         if (folder == null) {
497             return name;
498         }
499 
500         if (Pattern.matches(".* \\(\\d+\\)", name)) {
501             int pos = name.lastIndexOf(" (");
502 
503             name = name.substring(0, pos);
504         }
505 
506         StringBundler sb = new StringBundler(5);
507 
508         sb.append(name);
509         sb.append(StringPool.SPACE);
510         sb.append(StringPool.OPEN_PARENTHESIS);
511         sb.append(count);
512         sb.append(StringPool.CLOSE_PARENTHESIS);
513 
514         name = sb.toString();
515 
516         return getFolderName(companyId, groupId, parentFolderId, name, ++count);
517     }
518 
519     protected static String getFolderPath(
520         PortletDataContext context, long folderId) {
521 
522         StringBundler sb = new StringBundler(4);
523 
524         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
525         sb.append("/folders/");
526         sb.append(folderId);
527         sb.append(".xml");
528 
529         return sb.toString();
530     }
531 
532     protected static String getImageBinPath(
533         PortletDataContext context, IGImage image) {
534 
535         StringBundler sb = new StringBundler(5);
536 
537         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
538         sb.append("/bin/");
539         sb.append(image.getImageId());
540         sb.append(StringPool.PERIOD);
541         sb.append(image.getImageType());
542 
543         return sb.toString();
544     }
545 
546     protected static String getImagePath(
547         PortletDataContext context, IGImage image) {
548 
549         StringBundler sb = new StringBundler(4);
550 
551         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
552         sb.append("/images/");
553         sb.append(image.getImageId());
554         sb.append(".xml");
555 
556         return sb.toString();
557     }
558 
559     protected static String getImportFolderPath(
560         PortletDataContext context, long folderId) {
561 
562         StringBundler sb = new StringBundler(4);
563 
564         sb.append(context.getSourcePortletPath(PortletKeys.IMAGE_GALLERY));
565         sb.append("/folders/");
566         sb.append(folderId);
567         sb.append(".xml");
568 
569         return sb.toString();
570     }
571 
572     private static final String _NAMESPACE = "image_gallery";
573 
574     private static Log _log = LogFactoryUtil.getLog(
575         IGPortletDataHandlerImpl.class);
576 
577     private static PortletDataHandlerBoolean _categories =
578         new PortletDataHandlerBoolean(_NAMESPACE, "categories");
579 
580     private static PortletDataHandlerBoolean _foldersAndImages =
581         new PortletDataHandlerBoolean(
582             _NAMESPACE, "folders-and-images", true, true);
583 
584     private static PortletDataHandlerBoolean _ratings =
585         new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
586 
587     private static PortletDataHandlerBoolean _tags =
588         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
589 
590 }