1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
13   */
14  
15  package com.liferay.portlet.imagegallery.lar;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.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.IGImage;
42  import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
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          exportParentFolder(context, foldersEl, image.getFolderId());
74  
75          String path = getImagePath(context, image);
76  
77          if (context.isPathNotProcessed(path)) {
78              Element imageEl = imagesEl.addElement("image");
79  
80              imageEl.addAttribute("path", path);
81              imageEl.addAttribute("bin-path", getImageBinPath(context, image));
82  
83              if (context.getBooleanParameter(_NAMESPACE, "tags")) {
84                  context.addTagsEntries(IGImage.class, image.getImageId());
85              }
86  
87              image.setUserUuid(image.getUserUuid());
88  
89              Image largeImage = ImageUtil.findByPrimaryKey(
90                  image.getLargeImageId());
91  
92              image.setImageType(largeImage.getType());
93  
94              context.addPermissions(IGImage.class, image.getImageId());
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.setCreateDate(folder.getCreateDate());
117         serviceContext.setModifiedDate(folder.getModifiedDate());
118         serviceContext.setScopeGroupId(context.getGroupId());
119 
120         if ((parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
121             (parentFolderId == folder.getParentFolderId())) {
122 
123             String path = getImportFolderPath(context, parentFolderId);
124 
125             IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
126 
127             importFolder(context, folderPKs, parentFolder);
128 
129             parentFolderId = MapUtil.getLong(
130                 folderPKs, folder.getParentFolderId(),
131                 folder.getParentFolderId());
132         }
133 
134         IGFolder existingFolder = null;
135 
136         try {
137             if (parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
138                 IGFolderUtil.findByPrimaryKey(parentFolderId);
139             }
140 
141             if (context.getDataStrategy().equals(
142                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
143 
144                 existingFolder = IGFolderUtil.fetchByUUID_G(
145                     folder.getUuid(), context.getGroupId());
146 
147                 if (existingFolder == null) {
148                     String name = getFolderName(
149                         context.getCompanyId(), context.getGroupId(),
150                         parentFolderId, folder.getName(), 2);
151 
152                     existingFolder = IGFolderLocalServiceUtil.addFolder(
153                         folder.getUuid(), userId, parentFolderId, name,
154                         folder.getDescription(), serviceContext);
155                 }
156                 else {
157                     existingFolder = IGFolderLocalServiceUtil.updateFolder(
158                         existingFolder.getFolderId(), parentFolderId,
159                         folder.getName(), folder.getDescription(), false,
160                         serviceContext);
161                 }
162             }
163             else {
164                 String name = getFolderName(
165                     context.getCompanyId(), context.getGroupId(),
166                     parentFolderId, folder.getName(), 2);
167 
168                 existingFolder = IGFolderLocalServiceUtil.addFolder(
169                     userId, parentFolderId, name, folder.getDescription(),
170                     serviceContext);
171             }
172 
173             folderPKs.put(folder.getFolderId(), existingFolder.getFolderId());
174 
175             context.importPermissions(
176                 IGFolder.class, folder.getFolderId(),
177                 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.setCreateDate(image.getCreateDate());
225         serviceContext.setModifiedDate(image.getModifiedDate());
226         serviceContext.setTagsEntries(tagsEntries);
227 
228         if ((folderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
229             (folderId == image.getFolderId())) {
230 
231             String path = getImportFolderPath(context, folderId);
232 
233             IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
234 
235             importFolder(context, folderPKs, folder);
236 
237             folderId = MapUtil.getLong(
238                 folderPKs, image.getFolderId(), image.getFolderId());
239         }
240 
241         IGImage existingImage = null;
242 
243         try {
244             IGFolderUtil.findByPrimaryKey(folderId);
245 
246             if (context.getDataStrategy().equals(
247                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
248 
249                 try {
250                     existingImage = IGImageUtil.findByUUID_G(
251                         image.getUuid(), context.getGroupId());
252 
253                     existingImage = IGImageLocalServiceUtil.updateImage(
254                         userId, existingImage.getImageId(), folderId,
255                         image.getName(), image.getDescription(), imageFile,
256                         image.getImageType(), serviceContext);
257                 }
258                 catch (NoSuchImageException nsie) {
259                     existingImage = IGImageLocalServiceUtil.addImage(
260                         image.getUuid(), userId, folderId, image.getName(),
261                         image.getDescription(), imageFile, image.getImageType(),
262                         serviceContext);
263                 }
264             }
265             else {
266                 existingImage = IGImageLocalServiceUtil.addImage(
267                     userId, folderId, image.getName(), image.getDescription(),
268                     imageFile, image.getImageType(), serviceContext);
269             }
270 
271             context.importPermissions(
272                 IGImage.class, image.getImageId(), existingImage.getImageId());
273         }
274         catch (NoSuchFolderException nsfe) {
275             _log.error(
276                 "Could not find the parent folder for image " +
277                     image.getImageId());
278         }
279     }
280 
281     public PortletPreferences deleteData(
282             PortletDataContext context, String portletId,
283             PortletPreferences preferences)
284         throws PortletDataException {
285 
286         try {
287             if (!context.addPrimaryKey(
288                     IGPortletDataHandlerImpl.class, "deleteData")) {
289 
290                 IGFolderLocalServiceUtil.deleteFolders(context.getGroupId());
291             }
292 
293             return null;
294         }
295         catch (Exception e) {
296             throw new PortletDataException(e);
297         }
298     }
299 
300     public String exportData(
301             PortletDataContext context, String portletId,
302             PortletPreferences preferences)
303         throws PortletDataException {
304 
305         try {
306             context.addPermissions(
307                 "com.liferay.portlet.imagegallery", context.getGroupId());
308 
309             Document doc = SAXReaderUtil.createDocument();
310 
311             Element root = doc.addElement("image-gallery");
312 
313             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
314 
315             Element foldersEl = root.addElement("folders");
316             Element imagesEl = root.addElement("images");
317 
318             List<IGFolder> folders = IGFolderUtil.findByGroupId(
319                 context.getGroupId());
320 
321             for (IGFolder folder : folders) {
322                 exportFolder(context, foldersEl, imagesEl, folder);
323             }
324 
325             return doc.formattedString();
326         }
327         catch (Exception e) {
328             throw new PortletDataException(e);
329         }
330     }
331 
332     public PortletDataHandlerControl[] getExportControls() {
333         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
334     }
335 
336     public PortletDataHandlerControl[] getImportControls() {
337         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
338     }
339 
340     public PortletPreferences importData(
341             PortletDataContext context, String portletId,
342             PortletPreferences preferences, String data)
343         throws PortletDataException {
344 
345         try {
346             context.importPermissions(
347                 "com.liferay.portlet.imagegallery",
348                 context.getSourceGroupId(), context.getGroupId());
349 
350             Document doc = SAXReaderUtil.read(data);
351 
352             Element root = doc.getRootElement();
353 
354             List<Element> folderEls = root.element("folders").elements(
355                 "folder");
356 
357             Map<Long, Long> folderPKs =
358                 (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
359 
360             for (Element folderEl : folderEls) {
361                 String path = folderEl.attributeValue("path");
362 
363                 if (!context.isPathNotProcessed(path)) {
364                     continue;
365                 }
366 
367                 IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
368 
369                 importFolder(context, folderPKs, folder);
370             }
371 
372             List<Element> imageEls = root.element("images").elements("image");
373 
374             for (Element imageEl : imageEls) {
375                 String path = imageEl.attributeValue("path");
376 
377                 if (!context.isPathNotProcessed(path)) {
378                     continue;
379                 }
380 
381                 IGImage image = (IGImage)context.getZipEntryAsObject(path);
382 
383                 String binPath = imageEl.attributeValue("bin-path");
384 
385                 importImage(context, folderPKs, image, binPath);
386             }
387 
388             return null;
389         }
390         catch (Exception e) {
391             throw new PortletDataException(e);
392         }
393     }
394 
395     protected static void exportFolder(
396             PortletDataContext context, Element foldersEl, Element imagesEl,
397             IGFolder folder)
398         throws PortalException, SystemException {
399 
400         if (context.isWithinDateRange(folder.getModifiedDate())) {
401             exportParentFolder(context, foldersEl, folder.getParentFolderId());
402 
403             String path = getFolderPath(context, folder.getFolderId());
404 
405             if (context.isPathNotProcessed(path)) {
406                 Element folderEl = foldersEl.addElement("folder");
407 
408                 folderEl.addAttribute("path", path);
409 
410                 folder.setUserUuid(folder.getUserUuid());
411 
412                 context.addPermissions(IGFolder.class, folder.getFolderId());
413 
414                 context.addZipEntry(path, folder);
415             }
416         }
417 
418         List<IGImage> images = IGImageUtil.findByFolderId(folder.getFolderId());
419 
420         for (IGImage image : images) {
421             exportImage(context, foldersEl, imagesEl, image);
422         }
423     }
424 
425     protected static void exportParentFolder(
426             PortletDataContext context, Element foldersEl, long folderId)
427         throws PortalException, SystemException {
428 
429         if (folderId == IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
430             return;
431         }
432 
433         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
434 
435         exportParentFolder(context, foldersEl, folder.getParentFolderId());
436 
437         String path = getFolderPath(context, folder.getFolderId());
438 
439         if (context.isPathNotProcessed(path)) {
440             Element folderEl = foldersEl.addElement("folder");
441 
442             folderEl.addAttribute("path", path);
443 
444             folder.setUserUuid(folder.getUserUuid());
445 
446             context.addPermissions(IGFolder.class, folder.getFolderId());
447 
448             context.addZipEntry(path, folder);
449         }
450     }
451 
452     protected static String getFolderName(
453             long companyId, long groupId, long parentFolderId, String name,
454             int count)
455         throws SystemException {
456 
457         IGFolder folder = IGFolderUtil.fetchByG_P_N(
458             groupId, parentFolderId, name);
459 
460         if (folder == null) {
461             return name;
462         }
463 
464         if (Pattern.matches(".* \\(\\d+\\)", name)) {
465             int pos = name.lastIndexOf(" (");
466 
467             name = name.substring(0, pos);
468         }
469 
470         StringBundler sb = new StringBundler(5);
471 
472         sb.append(name);
473         sb.append(StringPool.SPACE);
474         sb.append(StringPool.OPEN_PARENTHESIS);
475         sb.append(count);
476         sb.append(StringPool.CLOSE_PARENTHESIS);
477 
478         name = sb.toString();
479 
480         return getFolderName(companyId, groupId, parentFolderId, name, ++count);
481     }
482 
483     protected static String getFolderPath(
484         PortletDataContext context, long folderId) {
485 
486         StringBundler sb = new StringBundler(4);
487 
488         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
489         sb.append("/folders/");
490         sb.append(folderId);
491         sb.append(".xml");
492 
493         return sb.toString();
494     }
495 
496     protected static String getImageBinPath(
497         PortletDataContext context, IGImage image) {
498 
499         StringBundler sb = new StringBundler(5);
500 
501         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
502         sb.append("/bin/");
503         sb.append(image.getImageId());
504         sb.append(StringPool.PERIOD);
505         sb.append(image.getImageType());
506 
507         return sb.toString();
508     }
509 
510     protected static String getImagePath(
511         PortletDataContext context, IGImage image) {
512 
513         StringBundler sb = new StringBundler(4);
514 
515         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
516         sb.append("/images/");
517         sb.append(image.getImageId());
518         sb.append(".xml");
519 
520         return sb.toString();
521     }
522 
523     protected static String getImportFolderPath(
524         PortletDataContext context, long folderId) {
525 
526         StringBundler sb = new StringBundler(4);
527 
528         sb.append(context.getSourcePortletPath(PortletKeys.IMAGE_GALLERY));
529         sb.append("/folders/");
530         sb.append(folderId);
531         sb.append(".xml");
532 
533         return sb.toString();
534     }
535 
536     private static final String _NAMESPACE = "image_gallery";
537 
538     private static final PortletDataHandlerBoolean _foldersAndImages =
539         new PortletDataHandlerBoolean(
540             _NAMESPACE, "folders-and-images", true, true);
541 
542     private static final PortletDataHandlerBoolean _tags =
543         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
544 
545     private static Log _log = LogFactoryUtil.getLog(
546         IGPortletDataHandlerImpl.class);
547 
548 }