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          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         exportParentFolder(context, foldersEl, image.getFolderId());
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         IGFolder existingFolder = null;
124 
125         try {
126             if (parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
127                 IGFolderUtil.findByPrimaryKey(parentFolderId);
128             }
129 
130             if (context.getDataStrategy().equals(
131                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
132 
133                 existingFolder = IGFolderUtil.fetchByUUID_G(
134                     folder.getUuid(), context.getGroupId());
135 
136                 if (existingFolder == null) {
137                     String name = getFolderName(
138                         context.getCompanyId(), context.getGroupId(),
139                         parentFolderId, folder.getName(), 2);
140 
141                     existingFolder = IGFolderLocalServiceUtil.addFolder(
142                         folder.getUuid(), userId, plid, parentFolderId,
143                         name, folder.getDescription(), addCommunityPermissions,
144                         addGuestPermissions);
145                 }
146                 else {
147                     existingFolder =
148                         IGFolderLocalServiceUtil.updateFolder(
149                         existingFolder.getFolderId(), parentFolderId,
150                         folder.getName(), folder.getDescription(),
151                         false);
152                 }
153             }
154             else {
155                 String name = getFolderName(
156                     context.getCompanyId(), context.getGroupId(),
157                     parentFolderId, folder.getName(), 2);
158 
159                 existingFolder = IGFolderLocalServiceUtil.addFolder(
160                     userId, plid, parentFolderId, name, folder.getDescription(),
161                     addCommunityPermissions, addGuestPermissions);
162             }
163 
164             folderPKs.put(folder.getFolderId(), existingFolder.getFolderId());
165         }
166         catch (NoSuchFolderException nsfe) {
167             _log.error(
168                 "Could not find the parent folder for folder " +
169                     folder.getFolderId());
170         }
171     }
172 
173     public static void importImage(
174             PortletDataContext context, Map<Long, Long> folderPKs,
175             IGImage image, String binPath)
176         throws Exception {
177 
178         long userId = context.getUserId(image.getUserUuid());
179         long folderId = MapUtil.getLong(
180             folderPKs, image.getFolderId(), image.getFolderId());
181 
182         File imageFile = null;
183 
184         byte[] bytes = context.getZipEntryAsByteArray(binPath);
185 
186         if (bytes == null) {
187             _log.error(
188                 "Could not find image file for image " + image.getImageId());
189 
190             return;
191         }
192         else {
193             imageFile = File.createTempFile(
194                 String.valueOf(image.getPrimaryKey()),
195                 StringPool.PERIOD + image.getImageType());
196 
197             FileUtil.write(imageFile, bytes);
198         }
199 
200         String[] tagsEntries = null;
201 
202         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
203             tagsEntries = context.getTagsEntries(
204                 IGImage.class, image.getImageId());
205         }
206 
207         boolean addCommunityPermissions = true;
208         boolean addGuestPermissions = true;
209 
210         IGImage existingImage = null;
211 
212         try {
213             IGFolderUtil.findByPrimaryKey(folderId);
214 
215             if (context.getDataStrategy().equals(
216                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
217 
218                 try {
219                     existingImage = IGImageFinderUtil.findByUuid_G(
220                         image.getUuid(), context.getGroupId());
221 
222                     IGImageLocalServiceUtil.updateImage(
223                         userId, existingImage.getImageId(), folderId,
224                         image.getName(), image.getDescription(), imageFile,
225                         image.getImageType(), tagsEntries);
226                 }
227                 catch (NoSuchImageException nsie) {
228                     IGImageLocalServiceUtil.addImage(
229                         image.getUuid(), userId, folderId,
230                         image.getName(), image.getDescription(), imageFile,
231                         image.getImageType(), tagsEntries,
232                         addCommunityPermissions, addGuestPermissions);
233                 }
234             }
235             else {
236                 IGImageLocalServiceUtil.addImage(
237                     userId, folderId, image.getName(),
238                     image.getDescription(), imageFile, image.getImageType(),
239                     tagsEntries, addCommunityPermissions, addGuestPermissions);
240             }
241         }
242         catch (NoSuchFolderException nsfe) {
243             _log.error(
244                 "Could not find the parent folder for image " +
245                     image.getImageId());
246         }
247     }
248 
249     public PortletPreferences deleteData(
250             PortletDataContext context, String portletId,
251             PortletPreferences prefs)
252         throws PortletDataException {
253 
254         try {
255             if (!context.addPrimaryKey(
256                     IGPortletDataHandlerImpl.class, "deleteData")) {
257 
258                 IGFolderLocalServiceUtil.deleteFolders(context.getGroupId());
259             }
260 
261             return null;
262         }
263         catch (Exception e) {
264             throw new PortletDataException(e);
265         }
266     }
267 
268     public String exportData(
269             PortletDataContext context, String portletId,
270             PortletPreferences prefs)
271         throws PortletDataException {
272 
273         try {
274             Document doc = SAXReaderUtil.createDocument();
275 
276             Element root = doc.addElement("image-gallery");
277 
278             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
279 
280             Element foldersEl = root.addElement("folders");
281             Element imagesEl = root.addElement("images");
282 
283             List<IGFolder> folders = IGFolderUtil.findByGroupId(
284                 context.getGroupId());
285 
286             for (IGFolder folder : folders) {
287                 exportFolder(context, foldersEl, imagesEl, folder);
288             }
289 
290             return doc.formattedString();
291         }
292         catch (Exception e) {
293             throw new PortletDataException(e);
294         }
295     }
296 
297     public PortletDataHandlerControl[] getExportControls() {
298         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
299     }
300 
301     public PortletDataHandlerControl[] getImportControls() {
302         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
303     }
304 
305     public PortletPreferences importData(
306             PortletDataContext context, String portletId,
307             PortletPreferences prefs, String data)
308         throws PortletDataException {
309 
310         try {
311             Document doc = SAXReaderUtil.read(data);
312 
313             Element root = doc.getRootElement();
314 
315             List<Element> folderEls = root.element("folders").elements(
316                 "folder");
317 
318             Map<Long, Long> folderPKs =
319                 (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
320 
321             for (Element folderEl : folderEls) {
322                 String path = folderEl.attributeValue("path");
323 
324                 if (!context.isPathNotProcessed(path)) {
325                     continue;
326                 }
327 
328                 IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
329 
330                 importFolder(context, folderPKs, folder);
331             }
332 
333             List<Element> imageEls = root.element("images").elements("image");
334 
335             for (Element imageEl : imageEls) {
336                 String path = imageEl.attributeValue("path");
337 
338                 if (!context.isPathNotProcessed(path)) {
339                     continue;
340                 }
341 
342                 IGImage image = (IGImage)context.getZipEntryAsObject(path);
343 
344                 String binPath = imageEl.attributeValue("bin-path");
345 
346                 importImage(context, folderPKs, image, binPath);
347             }
348 
349             return null;
350         }
351         catch (Exception e) {
352             throw new PortletDataException(e);
353         }
354     }
355 
356     public boolean isPublishToLiveByDefault() {
357         return false;
358     }
359 
360     protected static void exportFolder(
361             PortletDataContext context, Element foldersEl, Element imagesEl,
362             IGFolder folder)
363         throws PortalException, SystemException {
364 
365         if (context.isWithinDateRange(folder.getModifiedDate())) {
366             String path = getFolderPath(context, folder);
367 
368             if (context.isPathNotProcessed(path)) {
369                 Element folderEl = foldersEl.addElement("folder");
370 
371                 folderEl.addAttribute("path", path);
372 
373                 folder.setUserUuid(folder.getUserUuid());
374 
375                 context.addZipEntry(path, folder);
376             }
377 
378             exportParentFolder(context, foldersEl, folder.getParentFolderId());
379         }
380 
381         List<IGImage> images = IGImageUtil.findByFolderId(folder.getFolderId());
382 
383         for (IGImage image : images) {
384             exportImage(context, foldersEl, imagesEl, image);
385         }
386     }
387 
388     protected static void exportParentFolder(
389             PortletDataContext context, Element foldersEl, long folderId)
390         throws PortalException, SystemException {
391 
392         if (folderId == IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
393             return;
394         }
395 
396         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
397 
398         String path = getFolderPath(context, folder);
399 
400         if (context.isPathNotProcessed(path)) {
401             Element folderEl = foldersEl.addElement("folder");
402 
403             folderEl.addAttribute("path", path);
404 
405             folder.setUserUuid(folder.getUserUuid());
406 
407             context.addZipEntry(path, folder);
408         }
409 
410         exportParentFolder(context, foldersEl, folder.getParentFolderId());
411     }
412 
413     protected static String getFolderName(
414             long companyId, long groupId, long parentFolderId, String name,
415             int count)
416         throws SystemException {
417 
418         IGFolder folder = IGFolderUtil.fetchByG_P_N(
419             groupId, parentFolderId, name);
420 
421         if (folder == null) {
422             return name;
423         }
424 
425         if (Pattern.matches(".* \\(\\d+\\)", name)) {
426             int pos = name.lastIndexOf(" (");
427 
428             name = name.substring(0, pos);
429         }
430 
431         StringBuilder sb = new StringBuilder();
432 
433         sb.append(name);
434         sb.append(StringPool.SPACE);
435         sb.append(StringPool.OPEN_PARENTHESIS);
436         sb.append(count);
437         sb.append(StringPool.CLOSE_PARENTHESIS);
438 
439         name = sb.toString();
440 
441         return getFolderName(companyId, groupId, parentFolderId, name, ++count);
442     }
443 
444     protected static String getFolderPath(
445         PortletDataContext context, IGFolder folder) {
446 
447         StringBuilder sb = new StringBuilder();
448 
449         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
450         sb.append("/folders/");
451         sb.append(folder.getFolderId());
452         sb.append(".xml");
453 
454         return sb.toString();
455     }
456 
457     protected static String getImageBinPath(
458         PortletDataContext context, IGImage image) {
459 
460         StringBuilder sb = new StringBuilder();
461 
462         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
463         sb.append("/bin/");
464         sb.append(image.getImageId());
465         sb.append(StringPool.PERIOD);
466         sb.append(image.getImageType());
467 
468         return sb.toString();
469     }
470 
471     protected static String getImagePath(
472         PortletDataContext context, IGImage image) {
473 
474         StringBuilder sb = new StringBuilder();
475 
476         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
477         sb.append("/images/");
478         sb.append(image.getImageId());
479         sb.append(".xml");
480 
481         return sb.toString();
482     }
483 
484     private static final String _NAMESPACE = "image_gallery";
485 
486     private static final PortletDataHandlerBoolean _foldersAndImages =
487         new PortletDataHandlerBoolean(
488             _NAMESPACE, "folders-and-images", true, true);
489 
490     private static final PortletDataHandlerBoolean _tags =
491         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
492 
493     private static Log _log = LogFactory.getLog(IGPortletDataHandlerImpl.class);
494 
495 }