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