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