1   /**
2    * Copyright (c) 2000-2008 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.util.FileUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.xml.Document;
30  import com.liferay.portal.kernel.xml.Element;
31  import com.liferay.portal.kernel.xml.SAXReaderUtil;
32  import com.liferay.portal.lar.PortletDataContext;
33  import com.liferay.portal.lar.PortletDataException;
34  import com.liferay.portal.lar.PortletDataHandler;
35  import com.liferay.portal.lar.PortletDataHandlerBoolean;
36  import com.liferay.portal.lar.PortletDataHandlerControl;
37  import com.liferay.portal.lar.PortletDataHandlerKeys;
38  import com.liferay.portal.model.Image;
39  import com.liferay.portal.service.persistence.ImageUtil;
40  import com.liferay.portal.util.PortletKeys;
41  import com.liferay.portlet.imagegallery.NoSuchFolderException;
42  import com.liferay.portlet.imagegallery.NoSuchImageException;
43  import com.liferay.portlet.imagegallery.model.IGFolder;
44  import com.liferay.portlet.imagegallery.model.IGImage;
45  import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
46  import com.liferay.portlet.imagegallery.service.IGFolderLocalServiceUtil;
47  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
48  import com.liferay.portlet.imagegallery.service.persistence.IGFolderUtil;
49  import com.liferay.portlet.imagegallery.service.persistence.IGImageFinderUtil;
50  import com.liferay.portlet.imagegallery.service.persistence.IGImageUtil;
51  import com.liferay.util.MapUtil;
52  
53  import java.io.File;
54  
55  import java.util.List;
56  import java.util.Map;
57  import java.util.regex.Pattern;
58  
59  import javax.portlet.PortletPreferences;
60  
61  import org.apache.commons.logging.Log;
62  import org.apache.commons.logging.LogFactory;
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 implements PortletDataHandler {
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 plid = context.getPlid();
117         long parentFolderId = MapUtil.getLong(
118             folderPKs, folder.getParentFolderId(), folder.getParentFolderId());
119 
120         boolean addCommunityPermissions = true;
121         boolean addGuestPermissions = true;
122 
123         if ((parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
124             (parentFolderId == folder.getParentFolderId())) {
125 
126             String path = getImportFolderPath(context, parentFolderId);
127 
128             IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
129 
130             importFolder(context, folderPKs, parentFolder);
131 
132             parentFolderId = MapUtil.getLong(
133                 folderPKs, folder.getParentFolderId(),
134                 folder.getParentFolderId());
135         }
136 
137         IGFolder existingFolder = null;
138 
139         try {
140             if (parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
141                 IGFolderUtil.findByPrimaryKey(parentFolderId);
142             }
143 
144             if (context.getDataStrategy().equals(
145                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
146 
147                 existingFolder = IGFolderUtil.fetchByUUID_G(
148                     folder.getUuid(), context.getGroupId());
149 
150                 if (existingFolder == null) {
151                     String name = getFolderName(
152                         context.getCompanyId(), context.getGroupId(),
153                         parentFolderId, folder.getName(), 2);
154 
155                     existingFolder = IGFolderLocalServiceUtil.addFolder(
156                         folder.getUuid(), userId, plid, parentFolderId,
157                         name, folder.getDescription(), addCommunityPermissions,
158                         addGuestPermissions);
159                 }
160                 else {
161                     existingFolder =
162                         IGFolderLocalServiceUtil.updateFolder(
163                         existingFolder.getFolderId(), parentFolderId,
164                         folder.getName(), folder.getDescription(),
165                         false);
166                 }
167             }
168             else {
169                 String name = getFolderName(
170                     context.getCompanyId(), context.getGroupId(),
171                     parentFolderId, folder.getName(), 2);
172 
173                 existingFolder = IGFolderLocalServiceUtil.addFolder(
174                     userId, plid, parentFolderId, name, folder.getDescription(),
175                     addCommunityPermissions, addGuestPermissions);
176             }
177 
178             folderPKs.put(folder.getFolderId(), existingFolder.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 folderId = MapUtil.getLong(
194             folderPKs, image.getFolderId(), image.getFolderId());
195 
196         File imageFile = null;
197 
198         byte[] bytes = context.getZipEntryAsByteArray(binPath);
199 
200         if (bytes == null) {
201             _log.error(
202                 "Could not find image file for image " + image.getImageId());
203 
204             return;
205         }
206         else {
207             imageFile = File.createTempFile(
208                 String.valueOf(image.getPrimaryKey()),
209                 StringPool.PERIOD + image.getImageType());
210 
211             FileUtil.write(imageFile, bytes);
212         }
213 
214         String[] tagsEntries = null;
215 
216         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
217             tagsEntries = context.getTagsEntries(
218                 IGImage.class, image.getImageId());
219         }
220 
221         boolean addCommunityPermissions = true;
222         boolean addGuestPermissions = true;
223 
224         if ((folderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
225             (folderId == image.getFolderId())) {
226 
227             String path = getImportFolderPath(context, folderId);
228 
229             IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
230 
231             importFolder(context, folderPKs, folder);
232 
233             folderId = MapUtil.getLong(
234                 folderPKs, image.getFolderId(), image.getFolderId());
235         }
236 
237         IGImage existingImage = null;
238 
239         try {
240             IGFolderUtil.findByPrimaryKey(folderId);
241 
242             if (context.getDataStrategy().equals(
243                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
244 
245                 try {
246                     existingImage = IGImageFinderUtil.findByUuid_G(
247                         image.getUuid(), context.getGroupId());
248 
249                     IGImageLocalServiceUtil.updateImage(
250                         userId, existingImage.getImageId(), folderId,
251                         image.getName(), image.getDescription(), imageFile,
252                         image.getImageType(), tagsEntries);
253                 }
254                 catch (NoSuchImageException nsie) {
255                     IGImageLocalServiceUtil.addImage(
256                         image.getUuid(), userId, folderId,
257                         image.getName(), image.getDescription(), imageFile,
258                         image.getImageType(), tagsEntries,
259                         addCommunityPermissions, addGuestPermissions);
260                 }
261             }
262             else {
263                 IGImageLocalServiceUtil.addImage(
264                     userId, folderId, image.getName(),
265                     image.getDescription(), imageFile, image.getImageType(),
266                     tagsEntries, addCommunityPermissions, addGuestPermissions);
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 prefs)
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 prefs)
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 prefs, 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     public boolean isPublishToLiveByDefault() {
384         return false;
385     }
386 
387     protected static void exportFolder(
388             PortletDataContext context, Element foldersEl, Element imagesEl,
389             IGFolder folder)
390         throws PortalException, SystemException {
391 
392         if (context.isWithinDateRange(folder.getModifiedDate())) {
393             exportParentFolder(context, foldersEl, folder.getParentFolderId());
394 
395             String path = getFolderPath(context, folder.getFolderId());
396 
397             if (context.isPathNotProcessed(path)) {
398                 Element folderEl = foldersEl.addElement("folder");
399 
400                 folderEl.addAttribute("path", path);
401 
402                 folder.setUserUuid(folder.getUserUuid());
403 
404                 context.addZipEntry(path, folder);
405             }
406         }
407 
408         List<IGImage> images = IGImageUtil.findByFolderId(folder.getFolderId());
409 
410         for (IGImage image : images) {
411             exportImage(context, foldersEl, imagesEl, image);
412         }
413     }
414 
415     protected static void exportParentFolder(
416             PortletDataContext context, Element foldersEl, long folderId)
417         throws PortalException, SystemException {
418 
419         if (folderId == IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
420             return;
421         }
422 
423         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
424 
425         exportParentFolder(context, foldersEl, folder.getParentFolderId());
426 
427         String path = getFolderPath(context, folder.getFolderId());
428 
429         if (context.isPathNotProcessed(path)) {
430             Element folderEl = foldersEl.addElement("folder");
431 
432             folderEl.addAttribute("path", path);
433 
434             folder.setUserUuid(folder.getUserUuid());
435 
436             context.addZipEntry(path, folder);
437         }
438     }
439 
440     protected static String getFolderName(
441             long companyId, long groupId, long parentFolderId, String name,
442             int count)
443         throws SystemException {
444 
445         IGFolder folder = IGFolderUtil.fetchByG_P_N(
446             groupId, parentFolderId, name);
447 
448         if (folder == null) {
449             return name;
450         }
451 
452         if (Pattern.matches(".* \\(\\d+\\)", name)) {
453             int pos = name.lastIndexOf(" (");
454 
455             name = name.substring(0, pos);
456         }
457 
458         StringBuilder sb = new StringBuilder();
459 
460         sb.append(name);
461         sb.append(StringPool.SPACE);
462         sb.append(StringPool.OPEN_PARENTHESIS);
463         sb.append(count);
464         sb.append(StringPool.CLOSE_PARENTHESIS);
465 
466         name = sb.toString();
467 
468         return getFolderName(companyId, groupId, parentFolderId, name, ++count);
469     }
470 
471     protected static String getFolderPath(
472         PortletDataContext context, long folderId) {
473 
474         StringBuilder sb = new StringBuilder();
475 
476         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
477         sb.append("/folders/");
478         sb.append(folderId);
479         sb.append(".xml");
480 
481         return sb.toString();
482     }
483 
484     protected static String getImageBinPath(
485         PortletDataContext context, IGImage image) {
486 
487         StringBuilder sb = new StringBuilder();
488 
489         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
490         sb.append("/bin/");
491         sb.append(image.getImageId());
492         sb.append(StringPool.PERIOD);
493         sb.append(image.getImageType());
494 
495         return sb.toString();
496     }
497 
498     protected static String getImagePath(
499         PortletDataContext context, IGImage image) {
500 
501         StringBuilder sb = new StringBuilder();
502 
503         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
504         sb.append("/images/");
505         sb.append(image.getImageId());
506         sb.append(".xml");
507 
508         return sb.toString();
509     }
510 
511     protected static String getImportFolderPath(
512         PortletDataContext context, long folderId) {
513 
514         StringBuilder sb = new StringBuilder();
515 
516         sb.append(context.getImportPortletPath(PortletKeys.IMAGE_GALLERY));
517         sb.append("/folders/");
518         sb.append(folderId);
519         sb.append(".xml");
520 
521         return sb.toString();
522     }
523 
524     private static final String _NAMESPACE = "image_gallery";
525 
526     private static final PortletDataHandlerBoolean _foldersAndImages =
527         new PortletDataHandlerBoolean(
528             _NAMESPACE, "folders-and-images", true, true);
529 
530     private static final PortletDataHandlerBoolean _tags =
531         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
532 
533     private static Log _log = LogFactory.getLog(IGPortletDataHandlerImpl.class);
534 
535 }