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