1   /**
2    * Copyright (c) 2000-2007 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.softwarecatalog.service.impl;
24  
25  import com.liferay.counter.service.CounterLocalServiceUtil;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.search.Hits;
29  import com.liferay.portal.kernel.servlet.ImageServletTokenUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.OrderByComparator;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.lucene.LuceneFields;
36  import com.liferay.portal.lucene.LuceneUtil;
37  import com.liferay.portal.model.User;
38  import com.liferay.portal.model.impl.ResourceImpl;
39  import com.liferay.portal.plugin.ModuleId;
40  import com.liferay.portal.service.ResourceLocalServiceUtil;
41  import com.liferay.portal.service.impl.ImageLocalUtil;
42  import com.liferay.portal.service.persistence.UserUtil;
43  import com.liferay.portal.util.PortalUtil;
44  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
45  import com.liferay.portlet.ratings.service.RatingsStatsLocalServiceUtil;
46  import com.liferay.portlet.softwarecatalog.ProductEntryAuthorException;
47  import com.liferay.portlet.softwarecatalog.ProductEntryLicenseException;
48  import com.liferay.portlet.softwarecatalog.ProductEntryNameException;
49  import com.liferay.portlet.softwarecatalog.ProductEntryPageURLException;
50  import com.liferay.portlet.softwarecatalog.ProductEntryScreenshotsException;
51  import com.liferay.portlet.softwarecatalog.ProductEntryShortDescriptionException;
52  import com.liferay.portlet.softwarecatalog.ProductEntryTypeException;
53  import com.liferay.portlet.softwarecatalog.model.SCFrameworkVersion;
54  import com.liferay.portlet.softwarecatalog.model.SCLicense;
55  import com.liferay.portlet.softwarecatalog.model.SCProductEntry;
56  import com.liferay.portlet.softwarecatalog.model.SCProductScreenshot;
57  import com.liferay.portlet.softwarecatalog.model.SCProductVersion;
58  import com.liferay.portlet.softwarecatalog.service.SCProductScreenshotLocalServiceUtil;
59  import com.liferay.portlet.softwarecatalog.service.SCProductVersionLocalServiceUtil;
60  import com.liferay.portlet.softwarecatalog.service.base.SCProductEntryLocalServiceBaseImpl;
61  import com.liferay.portlet.softwarecatalog.service.persistence.SCProductEntryUtil;
62  import com.liferay.portlet.softwarecatalog.service.persistence.SCProductScreenshotUtil;
63  import com.liferay.portlet.softwarecatalog.service.persistence.SCProductVersionUtil;
64  import com.liferay.portlet.softwarecatalog.util.Indexer;
65  import com.liferay.util.Time;
66  import com.liferay.util.Version;
67  import com.liferay.util.lucene.HitsImpl;
68  import com.liferay.util.xml.DocUtil;
69  
70  import java.io.IOException;
71  
72  import java.net.MalformedURLException;
73  import java.net.URL;
74  
75  import java.util.Date;
76  import java.util.Iterator;
77  import java.util.List;
78  import java.util.Properties;
79  
80  import org.apache.commons.logging.Log;
81  import org.apache.commons.logging.LogFactory;
82  import org.apache.lucene.index.IndexWriter;
83  import org.apache.lucene.search.BooleanClause;
84  import org.apache.lucene.search.BooleanQuery;
85  import org.apache.lucene.search.Searcher;
86  
87  import org.dom4j.Document;
88  import org.dom4j.DocumentHelper;
89  import org.dom4j.Element;
90  
91  /**
92   * <a href="SCProductEntryLocalServiceImpl.java.html"><b><i>View Source</i></b>
93   * </a>
94   *
95   * @author Jorge Ferrer
96   * @author Brian Wing Shun Chan
97   *
98   */
99  public class SCProductEntryLocalServiceImpl
100     extends SCProductEntryLocalServiceBaseImpl {
101 
102     public SCProductEntry addProductEntry(
103             long userId, long plid, String name, String type, String tags,
104             String shortDescription, String longDescription, String pageURL,
105             String author, String repoGroupId, String repoArtifactId,
106             long[] licenseIds, List thumbnails, List fullImages,
107             boolean addCommunityPermissions, boolean addGuestPermissions)
108         throws PortalException, SystemException {
109 
110         return addProductEntry(
111             userId, plid, name, type, tags, shortDescription, longDescription,
112             pageURL, author, repoGroupId, repoArtifactId, licenseIds,
113             thumbnails, fullImages, Boolean.valueOf(addCommunityPermissions),
114             Boolean.valueOf(addGuestPermissions), null, null);
115     }
116 
117     public SCProductEntry addProductEntry(
118             long userId, long plid, String name, String type, String tags,
119             String shortDescription, String longDescription, String pageURL,
120             String author, String repoGroupId, String repoArtifactId,
121             long[] licenseIds, List thumbnails, List fullImages,
122             String[] communityPermissions, String[] guestPermissions)
123         throws PortalException, SystemException {
124 
125         return addProductEntry(
126             userId, plid, name, type, tags, shortDescription, longDescription,
127             pageURL, author, repoGroupId, repoArtifactId, licenseIds,
128             thumbnails, fullImages, null, null, communityPermissions,
129             guestPermissions);
130     }
131 
132     public SCProductEntry addProductEntry(
133             long userId, long plid, String name, String type, String tags,
134             String shortDescription, String longDescription, String pageURL,
135             String author, String repoGroupId, String repoArtifactId,
136             long[] licenseIds, List thumbnails, List fullImages,
137             Boolean addCommunityPermissions, Boolean addGuestPermissions,
138             String[] communityPermissions, String[] guestPermissions)
139         throws PortalException, SystemException {
140 
141         // Product entry
142 
143         User user = UserUtil.findByPrimaryKey(userId);
144         long groupId = PortalUtil.getPortletGroupId(plid);
145         tags = getTags(tags);
146         Date now = new Date();
147 
148         validate(
149             name, type, shortDescription, pageURL, author, licenseIds,
150             thumbnails, fullImages);
151 
152         long productEntryId = CounterLocalServiceUtil.increment();
153 
154         SCProductEntry productEntry = SCProductEntryUtil.create(productEntryId);
155 
156         productEntry.setGroupId(groupId);
157         productEntry.setCompanyId(user.getCompanyId());
158         productEntry.setUserId(user.getUserId());
159         productEntry.setUserName(user.getFullName());
160         productEntry.setCreateDate(now);
161         productEntry.setModifiedDate(now);
162         productEntry.setName(name);
163         productEntry.setType(type);
164         productEntry.setTags(tags);
165         productEntry.setShortDescription(shortDescription);
166         productEntry.setLongDescription(longDescription);
167         productEntry.setPageURL(pageURL);
168         productEntry.setAuthor(author);
169         productEntry.setRepoGroupId(repoGroupId);
170         productEntry.setRepoArtifactId(repoArtifactId);
171 
172         SCProductEntryUtil.update(productEntry);
173 
174         // Resources
175 
176         if ((addCommunityPermissions != null) &&
177             (addGuestPermissions != null)) {
178 
179             addProductEntryResources(
180                 productEntry, addCommunityPermissions.booleanValue(),
181                 addGuestPermissions.booleanValue());
182         }
183         else {
184             addProductEntryResources(
185                 productEntry, communityPermissions, guestPermissions);
186         }
187 
188         // Licenses
189 
190         SCProductEntryUtil.setSCLicenses(productEntryId, licenseIds);
191 
192         // Product screenshots
193 
194         saveProductScreenshots(productEntry, thumbnails, fullImages);
195 
196         // Lucene
197 
198         try {
199             Indexer.addProductEntry(
200                 productEntry.getCompanyId(), groupId, userId,
201                 user.getFullName(), productEntryId, name, now, StringPool.BLANK,
202                 type, shortDescription, longDescription, pageURL, repoGroupId,
203                 repoArtifactId);
204         }
205         catch (IOException ioe) {
206             _log.error("Indexing " + productEntryId, ioe);
207         }
208 
209         return productEntry;
210     }
211 
212     public void addProductEntryResources(
213             long productEntryId, boolean addCommunityPermissions,
214             boolean addGuestPermissions)
215         throws PortalException, SystemException {
216 
217         SCProductEntry productEntry = SCProductEntryUtil.findByPrimaryKey(
218             productEntryId);
219 
220         addProductEntryResources(
221             productEntry, addCommunityPermissions, addGuestPermissions);
222     }
223 
224     public void addProductEntryResources(
225             SCProductEntry productEntry, boolean addCommunityPermissions,
226             boolean addGuestPermissions)
227         throws PortalException, SystemException {
228 
229         ResourceLocalServiceUtil.addResources(
230             productEntry.getCompanyId(), productEntry.getGroupId(),
231             productEntry.getUserId(), SCProductEntry.class.getName(),
232             productEntry.getProductEntryId(), false, addCommunityPermissions,
233             addGuestPermissions);
234     }
235 
236     public void addProductEntryResources(
237             long productEntryId, String[] communityPermissions,
238             String[] guestPermissions)
239         throws PortalException, SystemException {
240 
241         SCProductEntry productEntry = SCProductEntryUtil.findByPrimaryKey(
242             productEntryId);
243 
244         addProductEntryResources(
245             productEntry, communityPermissions, guestPermissions);
246     }
247 
248     public void addProductEntryResources(
249             SCProductEntry productEntry, String[] communityPermissions,
250             String[] guestPermissions)
251         throws PortalException, SystemException {
252 
253         ResourceLocalServiceUtil.addModelResources(
254             productEntry.getCompanyId(), productEntry.getGroupId(),
255             productEntry.getUserId(), SCProductEntry.class.getName(),
256             productEntry.getProductEntryId(), communityPermissions,
257             guestPermissions);
258     }
259 
260     public void deleteProductEntry(long productEntryId)
261         throws PortalException, SystemException {
262 
263         SCProductEntry productEntry = SCProductEntryUtil.findByPrimaryKey(
264             productEntryId);
265 
266         deleteProductEntry(productEntry);
267     }
268 
269     public void deleteProductEntry(SCProductEntry productEntry)
270         throws PortalException, SystemException {
271 
272         // Lucene
273 
274         try {
275             Indexer.deleteProductEntry(
276                 productEntry.getCompanyId(), productEntry.getProductEntryId());
277         }
278         catch (IOException ioe) {
279             _log.error(
280                 "Deleting index " + productEntry.getProductEntryId(), ioe);
281         }
282 
283         // Product screenshots
284 
285         SCProductScreenshotLocalServiceUtil.deleteProductScreenshots(
286             productEntry.getProductEntryId());
287 
288         // Product versions
289 
290         SCProductVersionLocalServiceUtil.deleteProductVersions(
291             productEntry.getProductEntryId());
292 
293         // Ratings
294 
295         RatingsStatsLocalServiceUtil.deleteStats(
296             SCProductEntry.class.getName(), productEntry.getProductEntryId());
297 
298         // Message boards
299 
300         MBMessageLocalServiceUtil.deleteDiscussionMessages(
301             SCProductEntry.class.getName(), productEntry.getProductEntryId());
302 
303         // Resources
304 
305         ResourceLocalServiceUtil.deleteResource(
306             productEntry.getCompanyId(), SCProductEntry.class.getName(),
307             ResourceImpl.SCOPE_INDIVIDUAL, productEntry.getProductEntryId());
308 
309         // Product entry
310 
311         SCProductEntryUtil.remove(productEntry);
312     }
313 
314     public SCProductEntry getProductEntry(long productEntryId)
315         throws PortalException, SystemException {
316 
317         return SCProductEntryUtil.findByPrimaryKey(productEntryId);
318     }
319 
320     public List getProductEntries(long groupId, int begin, int end)
321         throws SystemException {
322 
323         return SCProductEntryUtil.findByGroupId(groupId, begin, end);
324     }
325 
326     public List getProductEntries(
327             long groupId, int begin, int end, OrderByComparator obc)
328         throws SystemException {
329 
330         return SCProductEntryUtil.findByGroupId(groupId, begin, end, obc);
331     }
332 
333     public List getProductEntries(long groupId, long userId, int begin, int end)
334         throws SystemException {
335 
336         return SCProductEntryUtil.findByG_U(groupId, userId, begin, end);
337     }
338 
339     public List getProductEntries(
340             long groupId, long userId, int begin, int end,
341             OrderByComparator obc)
342         throws SystemException {
343 
344         return SCProductEntryUtil.findByG_U(groupId, userId, begin, end, obc);
345     }
346 
347     public int getProductEntriesCount(long groupId)
348         throws SystemException {
349 
350         return SCProductEntryUtil.countByGroupId(groupId);
351     }
352 
353     public int getProductEntriesCount(long groupId, long userId)
354         throws SystemException {
355 
356         return SCProductEntryUtil.countByG_U(groupId, userId);
357     }
358 
359     public String getRepositoryXML(
360             long groupId, String baseImageURL, Date oldestDate,
361             int maxNumOfVersions, Properties repoSettings)
362         throws PortalException, SystemException{
363 
364         return getRepositoryXML(
365             groupId, null, baseImageURL, oldestDate, maxNumOfVersions,
366             repoSettings);
367     }
368 
369     public String getRepositoryXML(
370             long groupId, String version, String baseImageURL, Date oldestDate,
371             int maxNumOfVersions, Properties repoSettings)
372         throws PortalException, SystemException {
373 
374         Document doc = DocumentHelper.createDocument();
375 
376         doc.setXMLEncoding("UTF-8");
377 
378         Element root = doc.addElement("plugin-repository");
379 
380         Element settingsEl = root.addElement("settings");
381 
382         populateSettingsElement(settingsEl, repoSettings);
383 
384         List productEntries = SCProductEntryUtil.findByGroupId(groupId);
385 
386         Iterator itr = productEntries.iterator();
387 
388         while (itr.hasNext()) {
389             SCProductEntry productEntry = (SCProductEntry)itr.next();
390 
391             if (Validator.isNull(productEntry.getRepoGroupId()) ||
392                 Validator.isNull(productEntry.getRepoArtifactId())) {
393 
394                 continue;
395             }
396 
397             List productVersions = SCProductVersionUtil.findByProductEntryId(
398                 productEntry.getProductEntryId());
399 
400             Iterator itr2 = productVersions.iterator();
401 
402             for (int i = 1; itr2.hasNext(); i++) {
403                 SCProductVersion productVersion = (SCProductVersion)itr2.next();
404 
405                 if ((maxNumOfVersions > 0) && (maxNumOfVersions < i)) {
406                     break;
407                 }
408 
409                 if (!productVersion.isRepoStoreArtifact()) {
410                     continue;
411                 }
412 
413                 if ((oldestDate != null) &&
414                     (oldestDate.after(productVersion.getModifiedDate()))) {
415 
416                     continue;
417                 }
418 
419                 if (Validator.isNotNull(version) &&
420                     !isVersionSupported(
421                         version, productVersion.getFrameworkVersions())) {
422 
423                     continue;
424                 }
425 
426                 Element el = root.addElement("plugin-package");
427 
428                 populatePluginPackageElement(
429                     el, productEntry, productVersion, baseImageURL);
430             }
431         }
432 
433         return doc.asXML();
434     }
435 
436     public void reIndex(String[] ids) throws SystemException {
437         long companyId = GetterUtil.getLong(ids[0]);
438 
439         IndexWriter writer = null;
440 
441         try {
442             writer = LuceneUtil.getWriter(companyId);
443 
444             Iterator itr = SCProductEntryUtil.findByCompanyId(
445                 companyId).iterator();
446 
447             while (itr.hasNext()) {
448                 SCProductEntry productEntry = (SCProductEntry)itr.next();
449 
450                 long productEntryId = productEntry.getProductEntryId();
451 
452                 String version = StringPool.BLANK;
453 
454                 SCProductVersion latestProductVersion =
455                     productEntry.getLatestVersion();
456 
457                 if (latestProductVersion != null) {
458                     version = latestProductVersion.getVersion();
459                 }
460 
461                 try {
462                     org.apache.lucene.document.Document doc =
463                         Indexer.getAddProductEntryDocument(
464                             companyId, productEntry.getGroupId(),
465                             productEntry.getUserId(),
466                             productEntry.getUserName(),
467                             productEntryId, productEntry.getName(),
468                             productEntry.getModifiedDate(), version,
469                             productEntry.getType(),
470                             productEntry.getShortDescription(),
471                             productEntry.getLongDescription(),
472                             productEntry.getPageURL(),
473                             productEntry.getRepoGroupId(),
474                             productEntry.getRepoArtifactId());
475 
476                     writer.addDocument(doc);
477                 }
478                 catch (Exception e1) {
479                     _log.error("Reindexing " + productEntryId, e1);
480                 }
481             }
482         }
483         catch (SystemException se) {
484             throw se;
485         }
486         catch (Exception e2) {
487             throw new SystemException(e2);
488         }
489         finally {
490             try {
491                 if (writer != null) {
492                     LuceneUtil.write(companyId);
493                 }
494             }
495             catch (Exception e) {
496                 _log.error(e);
497             }
498         }
499     }
500 
501     public Hits search(
502             long companyId, long groupId, String keywords, String type)
503         throws SystemException {
504 
505         Searcher searcher = null;
506 
507         try {
508             HitsImpl hits = new HitsImpl();
509 
510             BooleanQuery contextQuery = new BooleanQuery();
511 
512             LuceneUtil.addRequiredTerm(
513                 contextQuery, LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
514             LuceneUtil.addRequiredTerm(
515                 contextQuery, LuceneFields.GROUP_ID, groupId);
516 
517             BooleanQuery fullQuery = new BooleanQuery();
518 
519             fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
520 
521             if (Validator.isNotNull(keywords)) {
522                 BooleanQuery searchQuery = new BooleanQuery();
523 
524                 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
525                 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
526 
527                 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
528             }
529 
530             if (Validator.isNotNull(type)) {
531                 BooleanQuery searchQuery = new BooleanQuery();
532 
533                 LuceneUtil.addRequiredTerm(searchQuery, "type", type);
534 
535                 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
536             }
537 
538             searcher = LuceneUtil.getSearcher(companyId);
539 
540             hits.recordHits(searcher.search(fullQuery), searcher);
541 
542             return hits;
543         }
544         catch (Exception e) {
545             return LuceneUtil.closeSearcher(searcher, keywords, e);
546         }
547     }
548 
549     public SCProductEntry updateProductEntry(
550             long productEntryId, String name, String type, String tags,
551             String shortDescription, String longDescription, String pageURL,
552             String author, String repoGroupId, String repoArtifactId,
553             long[] licenseIds, List thumbnails, List fullImages)
554         throws PortalException, SystemException {
555 
556         // Product entry
557 
558         tags = getTags(tags);
559         Date now = new Date();
560 
561         validate(
562             name, type, shortDescription, pageURL, author, licenseIds,
563             thumbnails, fullImages);
564 
565         SCProductEntry productEntry = SCProductEntryUtil.findByPrimaryKey(
566             productEntryId);
567 
568         productEntry.setModifiedDate(now);
569         productEntry.setName(name);
570         productEntry.setType(type);
571         productEntry.setTags(tags);
572         productEntry.setShortDescription(shortDescription);
573         productEntry.setLongDescription(longDescription);
574         productEntry.setPageURL(pageURL);
575         productEntry.setAuthor(author);
576         productEntry.setRepoGroupId(repoGroupId);
577         productEntry.setRepoArtifactId(repoArtifactId);
578 
579         SCProductEntryUtil.update(productEntry);
580 
581         // Licenses
582 
583         SCProductEntryUtil.setSCLicenses(productEntryId, licenseIds);
584 
585         // Product screenshots
586 
587         if (thumbnails.size() == 0) {
588             SCProductScreenshotLocalServiceUtil.deleteProductScreenshots(
589                 productEntryId);
590         }
591         else {
592             saveProductScreenshots(productEntry, thumbnails, fullImages);
593         }
594 
595         // Latest product version
596 
597         String version = StringPool.BLANK;
598 
599         List productVersions = SCProductVersionUtil.findByProductEntryId(
600             productEntryId, 0, 1);
601 
602         if (productVersions.size() > 0) {
603             SCProductVersion productVersion =
604                 (SCProductVersion)productVersions.get(0);
605 
606             productVersion.setModifiedDate(now);
607 
608             SCProductVersionUtil.update(productVersion);
609 
610             version = productVersion.getVersion();
611         }
612 
613         // Lucene
614 
615         try {
616             Indexer.updateProductEntry(
617                 productEntry.getCompanyId(), productEntry.getGroupId(),
618                 productEntry.getUserId(), productEntry.getUserName(),
619                 productEntryId, name, now, version, type, shortDescription,
620                 longDescription, pageURL, repoGroupId, repoArtifactId);
621         }
622         catch (IOException ioe) {
623             _log.error("Indexing " + productEntryId, ioe);
624         }
625 
626         return productEntry;
627     }
628 
629     protected String getTags(String tags) {
630         tags = tags.trim().toLowerCase();
631 
632         return StringUtil.merge(StringUtil.split(tags), ", ");
633     }
634 
635     protected boolean isVersionSupported(
636         String version, List supportedVersions) {
637 
638         Version currentVersion = Version.getInstance(version);
639 
640         Iterator iterator = supportedVersions.iterator();
641 
642         while (iterator.hasNext()) {
643             SCFrameworkVersion frameworkVersion =
644                 (SCFrameworkVersion)iterator.next();
645 
646             Version supportedVersion = Version.getInstance(
647                 frameworkVersion.getName());
648 
649             if (supportedVersion.includes(currentVersion)) {
650                 return true;
651             }
652         }
653 
654         return false;
655     }
656 
657     protected void populatePluginPackageElement(
658             Element el, SCProductEntry productEntry,
659             SCProductVersion productVersion, String baseImageURL)
660         throws PortalException, SystemException {
661 
662         DocUtil.add(el, "name", productEntry.getName());
663 
664         String moduleId = ModuleId.toString(
665             productEntry.getRepoGroupId(), productEntry.getRepoArtifactId(),
666             productVersion.getVersion(), "war");
667 
668         DocUtil.add(el, "module-id", moduleId);
669 
670         DocUtil.add(
671             el, "modified-date",
672             Time.getRFC822(productVersion.getModifiedDate()));
673 
674         Element typesEl = el.addElement("types");
675 
676         DocUtil.add(typesEl, "type", productEntry.getType());
677 
678         Element tagsEl = el.addElement("tags");
679 
680         String[] tags = StringUtil.split(productEntry.getTags());
681 
682         for (int i = 0; i < tags.length; i++) {
683             DocUtil.add(tagsEl, "tag", tags[i]);
684         }
685 
686         DocUtil.add(
687             el, "short-description", productEntry.getShortDescription());
688 
689         if (Validator.isNotNull(productEntry.getLongDescription())) {
690             DocUtil.add(
691                 el, "long-description", productEntry.getLongDescription());
692         }
693 
694         if (Validator.isNotNull(productVersion.getChangeLog())) {
695             DocUtil.add(el, "change-log", productVersion.getChangeLog());
696         }
697 
698         if (Validator.isNotNull(productVersion.getDirectDownloadURL())) {
699             DocUtil.add(
700                 el, "download-url", productVersion.getDirectDownloadURL());
701         }
702 
703         DocUtil.add(el, "author", productEntry.getAuthor());
704 
705         Element screenshotsEl = el.addElement("screenshots");
706 
707         Iterator itr = productEntry.getScreenshots().iterator();
708 
709         while (itr.hasNext()) {
710             SCProductScreenshot screenshot = (SCProductScreenshot)itr.next();
711 
712             long thumbnailId = screenshot.getThumbnailId();
713             long fullImageId = screenshot.getFullImageId();
714 
715             Element screenshotEl = screenshotsEl.addElement("screenshot");
716 
717             DocUtil.add(
718                 screenshotEl, "thumbnail-url",
719                 baseImageURL + "?img_id=" + thumbnailId + "&t=" +
720                     ImageServletTokenUtil.getToken(thumbnailId));
721             DocUtil.add(
722                 screenshotEl, "large-image-url",
723                 baseImageURL + "?img_id=" + fullImageId + "&t=" +
724                     ImageServletTokenUtil.getToken(fullImageId));
725         }
726 
727         Element licensesEl = el.addElement("licenses");
728 
729         itr = productEntry.getLicenses().iterator();
730 
731         while (itr.hasNext()) {
732             SCLicense license = (SCLicense)itr.next();
733 
734             Element licenseEl = licensesEl.addElement("license");
735 
736             licenseEl.addText(license.getName());
737             licenseEl.addAttribute(
738                 "osi-approved", String.valueOf(license.isOpenSource()));
739         }
740 
741         Element liferayVersionsEl = el.addElement("liferay-versions");
742 
743         itr = productVersion.getFrameworkVersions().iterator();
744 
745         while (itr.hasNext()) {
746             SCFrameworkVersion frameworkVersion =
747                 (SCFrameworkVersion)itr.next();
748 
749             DocUtil.add(
750                 liferayVersionsEl, "liferay-version",
751                 frameworkVersion.getName());
752         }
753     }
754 
755     protected void populateSettingsElement(
756         Element el, Properties repoSettings) {
757 
758         if (repoSettings == null) {
759             return;
760         }
761 
762         Iterator itr = repoSettings.keySet().iterator();
763 
764         while (itr.hasNext()) {
765             String key = (String) itr.next();
766 
767             Element settingEl = el.addElement("setting");
768 
769             settingEl.addAttribute("name", key);
770             settingEl.addAttribute("value", repoSettings.getProperty(key));
771         }
772     }
773 
774     protected void saveProductScreenshots(
775             SCProductEntry productEntry, List thumbnails, List fullImages)
776         throws SystemException {
777 
778         long productEntryId = productEntry.getProductEntryId();
779 
780         List productScreenshots =
781             SCProductScreenshotUtil.findByProductEntryId(productEntryId);
782 
783         if (thumbnails.size() < productScreenshots.size()) {
784             for (int i = thumbnails.size(); i < productScreenshots.size();
785                     i++) {
786 
787                 SCProductScreenshot productScreenshot =
788                     (SCProductScreenshot)productScreenshots.get(i);
789 
790                 SCProductScreenshotLocalServiceUtil.deleteProductScreenshot(
791                     productScreenshot);
792             }
793         }
794 
795         for (int i = 0; i < thumbnails.size(); i++) {
796             int priority = i;
797 
798             byte[] thumbnail = (byte[])thumbnails.get(i);
799             byte[] fullImage = (byte[])fullImages.get(i);
800 
801             SCProductScreenshot productScreenshot =
802                 SCProductScreenshotUtil.fetchByP_P(productEntryId, priority);
803 
804             if (productScreenshot == null) {
805                 long productScreenshotId = CounterLocalServiceUtil.increment();
806 
807                 long thumbnailId = CounterLocalServiceUtil.increment();
808                 long fullImageId = CounterLocalServiceUtil.increment();
809 
810                 productScreenshot = SCProductScreenshotUtil.create(
811                     productScreenshotId);
812 
813                 productScreenshot.setCompanyId(productEntry.getCompanyId());
814                 productScreenshot.setGroupId(productEntry.getGroupId());
815                 productScreenshot.setProductEntryId(productEntryId);
816                 productScreenshot.setThumbnailId(thumbnailId);
817                 productScreenshot.setFullImageId(fullImageId);
818                 productScreenshot.setPriority(priority);
819 
820                 SCProductScreenshotUtil.update(productScreenshot);
821             }
822 
823             ImageLocalUtil.updateImage(
824                 productScreenshot.getThumbnailId(), thumbnail);
825             ImageLocalUtil.updateImage(
826                 productScreenshot.getFullImageId(), fullImage);
827         }
828     }
829 
830     protected void validate(
831             String name, String type, String shortDescription, String pageURL,
832             String author, long[] licenseIds, List thumbnails, List fullImages)
833         throws PortalException {
834 
835         if (Validator.isNull(name)) {
836             throw new ProductEntryNameException();
837         }
838 
839         if (Validator.isNull(type)) {
840             throw new ProductEntryTypeException();
841         }
842 
843         if (Validator.isNull(shortDescription)) {
844             throw new ProductEntryShortDescriptionException();
845         }
846 
847         if (Validator.isNull(pageURL)) {
848             throw new ProductEntryPageURLException();
849         }
850         else {
851             try {
852                 new URL(pageURL);
853             }
854             catch (MalformedURLException murle) {
855                 throw new ProductEntryPageURLException();
856             }
857         }
858 
859         if (Validator.isNull(author)) {
860             throw new ProductEntryAuthorException();
861         }
862 
863         if (licenseIds.length == 0) {
864             throw new ProductEntryLicenseException();
865         }
866 
867         if (thumbnails.size() != fullImages.size()) {
868             throw new ProductEntryScreenshotsException();
869         }
870         else {
871             Iterator itr = thumbnails.iterator();
872 
873             while (itr.hasNext()) {
874                 if (itr.next() == null) {
875                     throw new ProductEntryScreenshotsException();
876                 }
877             }
878 
879             itr = fullImages.iterator();
880 
881             while (itr.hasNext()) {
882                 if (itr.next() == null) {
883                     throw new ProductEntryScreenshotsException();
884                 }
885             }
886         }
887     }
888 
889     private static Log _log =
890         LogFactory.getLog(SCProductEntryLocalServiceImpl.class);
891 
892 }