1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.imagegallery.lar;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.FileUtil;
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.lar.BasePortletDataHandler;
35  import com.liferay.portal.lar.PortletDataContext;
36  import com.liferay.portal.lar.PortletDataException;
37  import com.liferay.portal.lar.PortletDataHandlerBoolean;
38  import com.liferay.portal.lar.PortletDataHandlerControl;
39  import com.liferay.portal.lar.PortletDataHandlerKeys;
40  import com.liferay.portal.model.Image;
41  import com.liferay.portal.service.ServiceContext;
42  import com.liferay.portal.service.persistence.ImageUtil;
43  import com.liferay.portal.util.PortletKeys;
44  import com.liferay.portlet.imagegallery.NoSuchFolderException;
45  import com.liferay.portlet.imagegallery.NoSuchImageException;
46  import com.liferay.portlet.imagegallery.model.IGFolder;
47  import com.liferay.portlet.imagegallery.model.IGImage;
48  import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
49  import com.liferay.portlet.imagegallery.service.IGFolderLocalServiceUtil;
50  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
51  import com.liferay.portlet.imagegallery.service.persistence.IGFolderUtil;
52  import com.liferay.portlet.imagegallery.service.persistence.IGImageFinderUtil;
53  import com.liferay.portlet.imagegallery.service.persistence.IGImageUtil;
54  import com.liferay.util.MapUtil;
55  
56  import java.io.File;
57  
58  import java.util.List;
59  import java.util.Map;
60  import java.util.regex.Pattern;
61  
62  import javax.portlet.PortletPreferences;
63  
64  /**
65   * <a href="IGPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
66   *
67   * @author Bruno Farache
68   * @author Raymond Augé
69   *
70   */
71  public class IGPortletDataHandlerImpl extends BasePortletDataHandler {
72  
73      public static void exportImage(
74              PortletDataContext context, Element foldersEl, Element imagesEl,
75              IGImage image)
76          throws PortalException, SystemException {
77  
78          if (!context.isWithinDateRange(image.getModifiedDate())) {
79              return;
80          }
81  
82          exportParentFolder(context, foldersEl, image.getFolderId());
83  
84          String path = getImagePath(context, image);
85  
86          if (context.isPathNotProcessed(path)) {
87              Element imageEl = imagesEl.addElement("image");
88  
89              imageEl.addAttribute("path", path);
90              imageEl.addAttribute("bin-path", getImageBinPath(context, image));
91  
92              if (context.getBooleanParameter(_NAMESPACE, "tags")) {
93                  context.addTagsEntries(IGImage.class, image.getImageId());
94              }
95  
96              image.setUserUuid(image.getUserUuid());
97  
98              Image largeImage = ImageUtil.findByPrimaryKey(
99                  image.getLargeImageId());
100 
101             image.setImageType(largeImage.getType());
102 
103             context.addZipEntry(
104                 getImageBinPath(context, image), largeImage.getTextObj());
105 
106             context.addZipEntry(path, image);
107         }
108     }
109 
110     public static void importFolder(
111             PortletDataContext context, Map<Long, Long> folderPKs,
112             IGFolder folder)
113         throws Exception {
114 
115         long userId = context.getUserId(folder.getUserUuid());
116         long parentFolderId = MapUtil.getLong(
117             folderPKs, folder.getParentFolderId(), folder.getParentFolderId());
118 
119         ServiceContext serviceContext = new ServiceContext();
120 
121         serviceContext.setAddCommunityPermissions(true);
122         serviceContext.setAddGuestPermissions(true);
123         serviceContext.setScopeGroupId(context.getGroupId());
124 
125         if ((parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
126             (parentFolderId == folder.getParentFolderId())) {
127 
128             String path = getImportFolderPath(context, parentFolderId);
129 
130             IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
131 
132             importFolder(context, folderPKs, parentFolder);
133 
134             parentFolderId = MapUtil.getLong(
135                 folderPKs, folder.getParentFolderId(),
136                 folder.getParentFolderId());
137         }
138 
139         IGFolder existingFolder = null;
140 
141         try {
142             if (parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
143                 IGFolderUtil.findByPrimaryKey(parentFolderId);
144             }
145 
146             if (context.getDataStrategy().equals(
147                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
148 
149                 existingFolder = IGFolderUtil.fetchByUUID_G(
150                     folder.getUuid(), context.getGroupId());
151 
152                 if (existingFolder == null) {
153                     String name = getFolderName(
154                         context.getCompanyId(), context.getGroupId(),
155                         parentFolderId, folder.getName(), 2);
156 
157                     existingFolder = IGFolderLocalServiceUtil.addFolder(
158                         folder.getUuid(), userId, parentFolderId, name,
159                         folder.getDescription(), serviceContext);
160                 }
161                 else {
162                     existingFolder = IGFolderLocalServiceUtil.updateFolder(
163                         existingFolder.getFolderId(), parentFolderId,
164                         folder.getName(), folder.getDescription(), false);
165                 }
166             }
167             else {
168                 String name = getFolderName(
169                     context.getCompanyId(), context.getGroupId(),
170                     parentFolderId, folder.getName(), 2);
171 
172                 existingFolder = IGFolderLocalServiceUtil.addFolder(
173                     userId, parentFolderId, name, folder.getDescription(),
174                     serviceContext);
175             }
176 
177             folderPKs.put(folder.getFolderId(), existingFolder.getFolderId());
178         }
179         catch (NoSuchFolderException nsfe) {
180             _log.error(
181                 "Could not find the parent folder for folder " +
182                     folder.getFolderId());
183         }
184     }
185 
186     public static void importImage(
187             PortletDataContext context, Map<Long, Long> folderPKs,
188             IGImage image, String binPath)
189         throws Exception {
190 
191         long userId = context.getUserId(image.getUserUuid());
192         long folderId = MapUtil.getLong(
193             folderPKs, image.getFolderId(), image.getFolderId());
194 
195         File imageFile = null;
196 
197         byte[] bytes = context.getZipEntryAsByteArray(binPath);
198 
199         if (bytes == null) {
200             _log.error(
201                 "Could not find image file for image " + image.getImageId());
202 
203             return;
204         }
205         else {
206             imageFile = File.createTempFile(
207                 String.valueOf(image.getPrimaryKey()),
208                 StringPool.PERIOD + image.getImageType());
209 
210             FileUtil.write(imageFile, bytes);
211         }
212 
213         String[] tagsEntries = null;
214 
215         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
216             tagsEntries = context.getTagsEntries(
217                 IGImage.class, image.getImageId());
218         }
219 
220         ServiceContext serviceContext = new ServiceContext();
221 
222         serviceContext.setAddCommunityPermissions(true);
223         serviceContext.setAddGuestPermissions(true);
224         serviceContext.setTagsEntries(tagsEntries);
225 
226         if ((folderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
227             (folderId == image.getFolderId())) {
228 
229             String path = getImportFolderPath(context, folderId);
230 
231             IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
232 
233             importFolder(context, folderPKs, folder);
234 
235             folderId = MapUtil.getLong(
236                 folderPKs, image.getFolderId(), image.getFolderId());
237         }
238 
239         IGImage existingImage = null;
240 
241         try {
242             IGFolderUtil.findByPrimaryKey(folderId);
243 
244             if (context.getDataStrategy().equals(
245                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
246 
247                 try {
248                     existingImage = IGImageFinderUtil.findByUuid_G(
249                         image.getUuid(), context.getGroupId());
250 
251                     IGImageLocalServiceUtil.updateImage(
252                         userId, existingImage.getImageId(), folderId,
253                         image.getName(), image.getDescription(), imageFile,
254                         image.getImageType(), serviceContext);
255                 }
256                 catch (NoSuchImageException nsie) {
257                     IGImageLocalServiceUtil.addImage(
258                         image.getUuid(), userId, folderId, image.getName(),
259                         image.getDescription(), imageFile, image.getImageType(),
260                         serviceContext);
261                 }
262             }
263             else {
264                 IGImageLocalServiceUtil.addImage(
265                     userId, folderId, image.getName(), image.getDescription(),
266                     imageFile, image.getImageType(), serviceContext);
267             }
268         }
269         catch (NoSuchFolderException nsfe) {
270             _log.error(
271                 "Could not find the parent folder for image " +
272                     image.getImageId());
273         }
274     }
275 
276     public PortletPreferences deleteData(
277             PortletDataContext context, String portletId,
278             PortletPreferences preferences)
279         throws PortletDataException {
280 
281         try {
282             if (!context.addPrimaryKey(
283                     IGPortletDataHandlerImpl.class, "deleteData")) {
284 
285                 IGFolderLocalServiceUtil.deleteFolders(context.getGroupId());
286             }
287 
288             return null;
289         }
290         catch (Exception e) {
291             throw new PortletDataException(e);
292         }
293     }
294 
295     public String exportData(
296             PortletDataContext context, String portletId,
297             PortletPreferences preferences)
298         throws PortletDataException {
299 
300         try {
301             Document doc = SAXReaderUtil.createDocument();
302 
303             Element root = doc.addElement("image-gallery");
304 
305             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
306 
307             Element foldersEl = root.addElement("folders");
308             Element imagesEl = root.addElement("images");
309 
310             List<IGFolder> folders = IGFolderUtil.findByGroupId(
311                 context.getGroupId());
312 
313             for (IGFolder folder : folders) {
314                 exportFolder(context, foldersEl, imagesEl, folder);
315             }
316 
317             return doc.formattedString();
318         }
319         catch (Exception e) {
320             throw new PortletDataException(e);
321         }
322     }
323 
324     public PortletDataHandlerControl[] getExportControls() {
325         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
326     }
327 
328     public PortletDataHandlerControl[] getImportControls() {
329         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
330     }
331 
332     public PortletPreferences importData(
333             PortletDataContext context, String portletId,
334             PortletPreferences preferences, String data)
335         throws PortletDataException {
336 
337         try {
338             Document doc = SAXReaderUtil.read(data);
339 
340             Element root = doc.getRootElement();
341 
342             List<Element> folderEls = root.element("folders").elements(
343                 "folder");
344 
345             Map<Long, Long> folderPKs =
346                 (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
347 
348             for (Element folderEl : folderEls) {
349                 String path = folderEl.attributeValue("path");
350 
351                 if (!context.isPathNotProcessed(path)) {
352                     continue;
353                 }
354 
355                 IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
356 
357                 importFolder(context, folderPKs, folder);
358             }
359 
360             List<Element> imageEls = root.element("images").elements("image");
361 
362             for (Element imageEl : imageEls) {
363                 String path = imageEl.attributeValue("path");
364 
365                 if (!context.isPathNotProcessed(path)) {
366                     continue;
367                 }
368 
369                 IGImage image = (IGImage)context.getZipEntryAsObject(path);
370 
371                 String binPath = imageEl.attributeValue("bin-path");
372 
373                 importImage(context, folderPKs, image, binPath);
374             }
375 
376             return null;
377         }
378         catch (Exception e) {
379             throw new PortletDataException(e);
380         }
381     }
382 
383     protected static void exportFolder(
384             PortletDataContext context, Element foldersEl, Element imagesEl,
385             IGFolder folder)
386         throws PortalException, SystemException {
387 
388         if (context.isWithinDateRange(folder.getModifiedDate())) {
389             exportParentFolder(context, foldersEl, folder.getParentFolderId());
390 
391             String path = getFolderPath(context, folder.getFolderId());
392 
393             if (context.isPathNotProcessed(path)) {
394                 Element folderEl = foldersEl.addElement("folder");
395 
396                 folderEl.addAttribute("path", path);
397 
398                 folder.setUserUuid(folder.getUserUuid());
399 
400                 context.addZipEntry(path, folder);
401             }
402         }
403 
404         List<IGImage> images = IGImageUtil.findByFolderId(folder.getFolderId());
405 
406         for (IGImage image : images) {
407             exportImage(context, foldersEl, imagesEl, image);
408         }
409     }
410 
411     protected static void exportParentFolder(
412             PortletDataContext context, Element foldersEl, long folderId)
413         throws PortalException, SystemException {
414 
415         if (folderId == IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
416             return;
417         }
418 
419         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
420 
421         exportParentFolder(context, foldersEl, folder.getParentFolderId());
422 
423         String path = getFolderPath(context, folder.getFolderId());
424 
425         if (context.isPathNotProcessed(path)) {
426             Element folderEl = foldersEl.addElement("folder");
427 
428             folderEl.addAttribute("path", path);
429 
430             folder.setUserUuid(folder.getUserUuid());
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 SystemException {
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         StringBuilder sb = new StringBuilder();
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         StringBuilder sb = new StringBuilder();
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         StringBuilder sb = new StringBuilder();
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 getImagePath(
495         PortletDataContext context, IGImage image) {
496 
497         StringBuilder sb = new StringBuilder();
498 
499         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
500         sb.append("/images/");
501         sb.append(image.getImageId());
502         sb.append(".xml");
503 
504         return sb.toString();
505     }
506 
507     protected static String getImportFolderPath(
508         PortletDataContext context, long folderId) {
509 
510         StringBuilder sb = new StringBuilder();
511 
512         sb.append(context.getSourcePortletPath(PortletKeys.IMAGE_GALLERY));
513         sb.append("/folders/");
514         sb.append(folderId);
515         sb.append(".xml");
516 
517         return sb.toString();
518     }
519 
520     private static final String _NAMESPACE = "image_gallery";
521 
522     private static final PortletDataHandlerBoolean _foldersAndImages =
523         new PortletDataHandlerBoolean(
524             _NAMESPACE, "folders-and-images", true, true);
525 
526     private static final PortletDataHandlerBoolean _tags =
527         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
528 
529     private static Log _log =
530          LogFactoryUtil.getLog(IGPortletDataHandlerImpl.class);
531 
532 }