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