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