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