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