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.ResourceConstants;
37  import com.liferay.portal.model.User;
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<byte[]> thumbnails, List<byte[]> 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<byte[]> thumbnails, List<byte[]> 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<byte[]> thumbnails, List<byte[]> 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, false);
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         List<SCProductEntry> productEntries =
259             scProductEntryPersistence.findByGroupId(groupId);
260 
261         for (SCProductEntry productEntry : productEntries) {
262             deleteProductEntry(productEntry);
263         }
264     }
265 
266     public void deleteProductEntry(long productEntryId)
267         throws PortalException, SystemException {
268 
269         SCProductEntry productEntry =
270             scProductEntryPersistence.findByPrimaryKey(productEntryId);
271 
272         deleteProductEntry(productEntry);
273     }
274 
275     public void deleteProductEntry(SCProductEntry productEntry)
276         throws PortalException, SystemException {
277 
278         // Lucene
279 
280         try {
281             Indexer.deleteProductEntry(
282                 productEntry.getCompanyId(), productEntry.getProductEntryId());
283         }
284         catch (IOException ioe) {
285             _log.error(
286                 "Deleting index " + productEntry.getProductEntryId(), ioe);
287         }
288 
289         // Product screenshots
290 
291         scProductScreenshotLocalService.deleteProductScreenshots(
292             productEntry.getProductEntryId());
293 
294         // Product versions
295 
296         scProductVersionLocalService.deleteProductVersions(
297             productEntry.getProductEntryId());
298 
299         // Ratings
300 
301         ratingsStatsLocalService.deleteStats(
302             SCProductEntry.class.getName(), productEntry.getProductEntryId());
303 
304         // Message boards
305 
306         mbMessageLocalService.deleteDiscussionMessages(
307             SCProductEntry.class.getName(), productEntry.getProductEntryId());
308 
309         // Resources
310 
311         resourceLocalService.deleteResource(
312             productEntry.getCompanyId(), SCProductEntry.class.getName(),
313             ResourceConstants.SCOPE_INDIVIDUAL,
314             productEntry.getProductEntryId());
315 
316         // Product entry
317 
318         scProductEntryPersistence.remove(productEntry);
319     }
320 
321     public SCProductEntry getProductEntry(long productEntryId)
322         throws PortalException, SystemException {
323 
324         return scProductEntryPersistence.findByPrimaryKey(productEntryId);
325     }
326 
327     public List<SCProductEntry> getProductEntries(
328             long groupId, int begin, int end)
329         throws SystemException {
330 
331         return scProductEntryPersistence.findByGroupId(groupId, begin, end);
332     }
333 
334     public List<SCProductEntry> 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<SCProductEntry> getProductEntries(
343             long groupId, long userId, int begin, int end)
344         throws SystemException {
345 
346         return scProductEntryPersistence.findByG_U(groupId, userId, begin, end);
347     }
348 
349     public List<SCProductEntry> getProductEntries(
350             long groupId, long userId, int begin, int end,
351             OrderByComparator obc)
352         throws SystemException {
353 
354         return scProductEntryPersistence.findByG_U(
355             groupId, userId, begin, end, obc);
356     }
357 
358     public int getProductEntriesCount(long groupId)
359         throws SystemException {
360 
361         return scProductEntryPersistence.countByGroupId(groupId);
362     }
363 
364     public int getProductEntriesCount(long groupId, long userId)
365         throws SystemException {
366 
367         return scProductEntryPersistence.countByG_U(groupId, userId);
368     }
369 
370     public String getRepositoryXML(
371             long groupId, String baseImageURL, Date oldestDate,
372             int maxNumOfVersions, Properties repoSettings)
373         throws PortalException, SystemException {
374 
375         return getRepositoryXML(
376             groupId, null, baseImageURL, oldestDate, maxNumOfVersions,
377             repoSettings);
378     }
379 
380     public String getRepositoryXML(
381             long groupId, String version, String baseImageURL, Date oldestDate,
382             int maxNumOfVersions, Properties repoSettings)
383         throws PortalException, SystemException {
384 
385         Document doc = DocumentHelper.createDocument();
386 
387         doc.setXMLEncoding(StringPool.UTF8);
388 
389         Element root = doc.addElement("plugin-repository");
390 
391         Element settingsEl = root.addElement("settings");
392 
393         populateSettingsElement(settingsEl, repoSettings);
394 
395         List<SCProductEntry> productEntries =
396             scProductEntryPersistence.findByGroupId(groupId);
397 
398         for (SCProductEntry productEntry : productEntries) {
399             if (Validator.isNull(productEntry.getRepoGroupId()) ||
400                 Validator.isNull(productEntry.getRepoArtifactId())) {
401 
402                 continue;
403             }
404 
405             List<SCProductVersion> productVersions =
406                 scProductVersionPersistence.findByProductEntryId(
407                     productEntry.getProductEntryId());
408 
409             for (int i = 0; i < productVersions.size(); i++) {
410                 SCProductVersion productVersion = productVersions.get(i);
411 
412                 if ((maxNumOfVersions > 0) && (maxNumOfVersions < (i + 1))) {
413                     break;
414                 }
415 
416                 if (!productVersion.isRepoStoreArtifact()) {
417                     continue;
418                 }
419 
420                 if ((oldestDate != null) &&
421                     (oldestDate.after(productVersion.getModifiedDate()))) {
422 
423                     continue;
424                 }
425 
426                 if (Validator.isNotNull(version) &&
427                     !isVersionSupported(
428                         version, productVersion.getFrameworkVersions())) {
429 
430                     continue;
431                 }
432 
433                 Element el = root.addElement("plugin-package");
434 
435                 populatePluginPackageElement(
436                     el, productEntry, productVersion, baseImageURL);
437             }
438         }
439 
440         return doc.asXML();
441     }
442 
443     public void reIndex(String[] ids) throws SystemException {
444         if (LuceneUtil.INDEX_READ_ONLY) {
445             return;
446         }
447 
448         long companyId = GetterUtil.getLong(ids[0]);
449 
450         IndexWriter writer = null;
451 
452         try {
453             writer = LuceneUtil.getWriter(companyId);
454 
455             List<SCProductEntry> productEntries =
456                 scProductEntryPersistence.findByCompanyId(companyId);
457 
458             for (SCProductEntry productEntry : productEntries) {
459                 long productEntryId = productEntry.getProductEntryId();
460 
461                 String version = StringPool.BLANK;
462 
463                 SCProductVersion latestProductVersion =
464                     productEntry.getLatestVersion();
465 
466                 if (latestProductVersion != null) {
467                     version = latestProductVersion.getVersion();
468                 }
469 
470                 try {
471                     org.apache.lucene.document.Document doc =
472                         Indexer.getAddProductEntryDocument(
473                             companyId, productEntry.getGroupId(),
474                             productEntry.getUserId(),
475                             productEntry.getUserName(),
476                             productEntryId, productEntry.getName(),
477                             productEntry.getModifiedDate(), version,
478                             productEntry.getType(),
479                             productEntry.getShortDescription(),
480                             productEntry.getLongDescription(),
481                             productEntry.getPageURL(),
482                             productEntry.getRepoGroupId(),
483                             productEntry.getRepoArtifactId());
484 
485                     writer.addDocument(doc);
486                 }
487                 catch (Exception e1) {
488                     _log.error("Reindexing " + productEntryId, e1);
489                 }
490             }
491         }
492         catch (SystemException se) {
493             throw se;
494         }
495         catch (Exception e2) {
496             throw new SystemException(e2);
497         }
498         finally {
499             try {
500                 if (writer != null) {
501                     LuceneUtil.write(companyId);
502                 }
503             }
504             catch (Exception e) {
505                 _log.error(e);
506             }
507         }
508     }
509 
510     public Hits search(
511             long companyId, long groupId, String keywords, String type)
512         throws SystemException {
513 
514         Searcher searcher = null;
515 
516         try {
517             HitsImpl hits = new HitsImpl();
518 
519             BooleanQuery contextQuery = new BooleanQuery();
520 
521             LuceneUtil.addRequiredTerm(
522                 contextQuery, LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
523             LuceneUtil.addRequiredTerm(
524                 contextQuery, LuceneFields.GROUP_ID, groupId);
525 
526             BooleanQuery fullQuery = new BooleanQuery();
527 
528             fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
529 
530             if (Validator.isNotNull(keywords)) {
531                 BooleanQuery searchQuery = new BooleanQuery();
532 
533                 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
534                 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
535 
536                 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
537             }
538 
539             if (Validator.isNotNull(type)) {
540                 BooleanQuery searchQuery = new BooleanQuery();
541 
542                 LuceneUtil.addRequiredTerm(searchQuery, "type", type);
543 
544                 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
545             }
546 
547             searcher = LuceneUtil.getSearcher(companyId);
548 
549             hits.recordHits(searcher.search(fullQuery), searcher);
550 
551             return hits;
552         }
553         catch (Exception e) {
554             return LuceneUtil.closeSearcher(searcher, keywords, e);
555         }
556     }
557 
558     public SCProductEntry updateProductEntry(
559             long productEntryId, String name, String type, String tags,
560             String shortDescription, String longDescription, String pageURL,
561             String author, String repoGroupId, String repoArtifactId,
562             long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages)
563         throws PortalException, SystemException {
564 
565         // Product entry
566 
567         tags = getTags(tags);
568         repoGroupId = repoGroupId.trim().toLowerCase();
569         repoArtifactId = repoArtifactId.trim().toLowerCase();
570         Date now = new Date();
571 
572         validate(
573             productEntryId, name, type, shortDescription, pageURL, author,
574             repoGroupId, repoArtifactId, licenseIds, thumbnails, fullImages);
575 
576         SCProductEntry productEntry =
577             scProductEntryPersistence.findByPrimaryKey(productEntryId);
578 
579         productEntry.setModifiedDate(now);
580         productEntry.setName(name);
581         productEntry.setType(type);
582         productEntry.setTags(tags);
583         productEntry.setShortDescription(shortDescription);
584         productEntry.setLongDescription(longDescription);
585         productEntry.setPageURL(pageURL);
586         productEntry.setAuthor(author);
587         productEntry.setRepoGroupId(repoGroupId);
588         productEntry.setRepoArtifactId(repoArtifactId);
589 
590         scProductEntryPersistence.update(productEntry, false);
591 
592         // Licenses
593 
594         scProductEntryPersistence.setSCLicenses(productEntryId, licenseIds);
595 
596         // Product screenshots
597 
598         if (thumbnails.size() == 0) {
599             scProductScreenshotLocalService.deleteProductScreenshots(
600                 productEntryId);
601         }
602         else {
603             saveProductScreenshots(productEntry, thumbnails, fullImages);
604         }
605 
606         // Latest product version
607 
608         String version = StringPool.BLANK;
609 
610         List<SCProductVersion> productVersions =
611             scProductVersionPersistence.findByProductEntryId(
612                 productEntryId, 0, 1);
613 
614         if (productVersions.size() > 0) {
615             SCProductVersion productVersion = productVersions.get(0);
616 
617             productVersion.setModifiedDate(now);
618 
619             scProductVersionPersistence.update(productVersion, false);
620 
621             version = productVersion.getVersion();
622         }
623 
624         // Lucene
625 
626         try {
627             Indexer.updateProductEntry(
628                 productEntry.getCompanyId(), productEntry.getGroupId(),
629                 productEntry.getUserId(), productEntry.getUserName(),
630                 productEntryId, name, now, version, type, shortDescription,
631                 longDescription, pageURL, repoGroupId, repoArtifactId);
632         }
633         catch (IOException ioe) {
634             _log.error("Indexing " + productEntryId, ioe);
635         }
636 
637         return productEntry;
638     }
639 
640     protected String getTags(String tags) {
641         tags = tags.trim().toLowerCase();
642 
643         return StringUtil.merge(StringUtil.split(tags), ", ");
644     }
645 
646     protected boolean isVersionSupported(
647         String version, List<SCFrameworkVersion> frameworkVersions) {
648 
649         Version currentVersion = Version.getInstance(version);
650 
651         for (SCFrameworkVersion frameworkVersion : frameworkVersions) {
652             Version supportedVersion = Version.getInstance(
653                 frameworkVersion.getName());
654 
655             if (supportedVersion.includes(currentVersion)) {
656                 return true;
657             }
658         }
659 
660         return false;
661     }
662 
663     protected void populatePluginPackageElement(
664             Element el, SCProductEntry productEntry,
665             SCProductVersion productVersion, String baseImageURL)
666         throws PortalException, SystemException {
667 
668         DocUtil.add(el, "name", productEntry.getName());
669 
670         String moduleId = ModuleId.toString(
671             productEntry.getRepoGroupId(), productEntry.getRepoArtifactId(),
672             productVersion.getVersion(), "war");
673 
674         DocUtil.add(el, "module-id", moduleId);
675 
676         DocUtil.add(
677             el, "modified-date",
678             Time.getRFC822(productVersion.getModifiedDate()));
679 
680         Element typesEl = el.addElement("types");
681 
682         DocUtil.add(typesEl, "type", productEntry.getType());
683 
684         Element tagsEl = el.addElement("tags");
685 
686         String[] tags = StringUtil.split(productEntry.getTags());
687 
688         for (int i = 0; i < tags.length; i++) {
689             DocUtil.add(tagsEl, "tag", tags[i]);
690         }
691 
692         DocUtil.add(
693             el, "short-description", productEntry.getShortDescription());
694 
695         if (Validator.isNotNull(productEntry.getLongDescription())) {
696             DocUtil.add(
697                 el, "long-description", productEntry.getLongDescription());
698         }
699 
700         if (Validator.isNotNull(productVersion.getChangeLog())) {
701             DocUtil.add(el, "change-log", productVersion.getChangeLog());
702         }
703 
704         if (Validator.isNotNull(productVersion.getDirectDownloadURL())) {
705             DocUtil.add(
706                 el, "download-url", productVersion.getDirectDownloadURL());
707         }
708 
709         DocUtil.add(el, "author", productEntry.getAuthor());
710 
711         Element screenshotsEl = el.addElement("screenshots");
712 
713         for (SCProductScreenshot screenshot : productEntry.getScreenshots()) {
714             long thumbnailId = screenshot.getThumbnailId();
715             long fullImageId = screenshot.getFullImageId();
716 
717             Element screenshotEl = screenshotsEl.addElement("screenshot");
718 
719             DocUtil.add(
720                 screenshotEl, "thumbnail-url",
721                 baseImageURL + "?img_id=" + thumbnailId + "&t=" +
722                     ImageServletTokenUtil.getToken(thumbnailId));
723             DocUtil.add(
724                 screenshotEl, "large-image-url",
725                 baseImageURL + "?img_id=" + fullImageId + "&t=" +
726                     ImageServletTokenUtil.getToken(fullImageId));
727         }
728 
729         Element licensesEl = el.addElement("licenses");
730 
731         for (SCLicense license : productEntry.getLicenses()) {
732             Element licenseEl = licensesEl.addElement("license");
733 
734             licenseEl.addText(license.getName());
735             licenseEl.addAttribute(
736                 "osi-approved", String.valueOf(license.isOpenSource()));
737         }
738 
739         Element liferayVersionsEl = el.addElement("liferay-versions");
740 
741         for (SCFrameworkVersion frameworkVersion :
742                 productVersion.getFrameworkVersions()) {
743 
744             DocUtil.add(
745                 liferayVersionsEl, "liferay-version",
746                 frameworkVersion.getName());
747         }
748     }
749 
750     protected void populateSettingsElement(
751         Element el, Properties repoSettings) {
752 
753         if (repoSettings == null) {
754             return;
755         }
756 
757         Iterator<Object> itr = repoSettings.keySet().iterator();
758 
759         while (itr.hasNext()) {
760             String key = (String)itr.next();
761 
762             Element settingEl = el.addElement("setting");
763 
764             settingEl.addAttribute("name", key);
765             settingEl.addAttribute("value", repoSettings.getProperty(key));
766         }
767     }
768 
769     protected void saveProductScreenshots(
770             SCProductEntry productEntry, List<byte[]> thumbnails,
771             List<byte[]> fullImages)
772         throws SystemException {
773 
774         long productEntryId = productEntry.getProductEntryId();
775 
776         List<SCProductScreenshot> productScreenshots =
777             scProductScreenshotPersistence.findByProductEntryId(productEntryId);
778 
779         if (thumbnails.size() < productScreenshots.size()) {
780             for (int i = thumbnails.size(); i < productScreenshots.size();
781                     i++) {
782 
783                 SCProductScreenshot productScreenshot =
784                     productScreenshots.get(i);
785 
786                 scProductScreenshotLocalService.deleteProductScreenshot(
787                     productScreenshot);
788             }
789         }
790 
791         for (int i = 0; i < thumbnails.size(); i++) {
792             int priority = i;
793 
794             byte[] thumbnail = thumbnails.get(i);
795             byte[] fullImage = fullImages.get(i);
796 
797             SCProductScreenshot productScreenshot =
798                 scProductScreenshotPersistence.fetchByP_P(
799                     productEntryId, priority);
800 
801             if (productScreenshot == null) {
802                 long productScreenshotId = counterLocalService.increment();
803 
804                 long thumbnailId = counterLocalService.increment();
805                 long fullImageId = counterLocalService.increment();
806 
807                 productScreenshot = scProductScreenshotPersistence.create(
808                     productScreenshotId);
809 
810                 productScreenshot.setCompanyId(productEntry.getCompanyId());
811                 productScreenshot.setGroupId(productEntry.getGroupId());
812                 productScreenshot.setProductEntryId(productEntryId);
813                 productScreenshot.setThumbnailId(thumbnailId);
814                 productScreenshot.setFullImageId(fullImageId);
815                 productScreenshot.setPriority(priority);
816 
817                 scProductScreenshotPersistence.update(productScreenshot, false);
818             }
819 
820             ImageLocalUtil.updateImage(
821                 productScreenshot.getThumbnailId(), thumbnail);
822             ImageLocalUtil.updateImage(
823                 productScreenshot.getFullImageId(), fullImage);
824         }
825     }
826 
827     protected void validate(
828             long productEntryId, String name, String type,
829             String shortDescription, String pageURL, String author,
830             String repoGroupId, String repoArtifactId, long[] licenseIds,
831             List<byte[]> thumbnails, List<byte[]> fullImages)
832         throws PortalException, SystemException {
833 
834         if (Validator.isNull(name)) {
835             throw new ProductEntryNameException();
836         }
837 
838         if (Validator.isNull(type)) {
839             throw new ProductEntryTypeException();
840         }
841 
842         if (Validator.isNull(shortDescription)) {
843             throw new ProductEntryShortDescriptionException();
844         }
845 
846         if (Validator.isNull(pageURL)) {
847             throw new ProductEntryPageURLException();
848         }
849         else {
850             try {
851                 new URL(pageURL);
852             }
853             catch (MalformedURLException murle) {
854                 throw new ProductEntryPageURLException();
855             }
856         }
857 
858         if (Validator.isNull(author)) {
859             throw new ProductEntryAuthorException();
860         }
861 
862         try {
863             SCProductEntry productEntry = scProductEntryPersistence.findByRG_RA(
864                 repoGroupId, repoArtifactId);
865 
866             if (productEntry.getProductEntryId() != productEntryId) {
867                 throw new DuplicateProductEntryModuleIdException();
868             }
869         }
870         catch (NoSuchProductEntryException nspee) {
871         }
872 
873         if (licenseIds.length == 0) {
874             throw new ProductEntryLicenseException();
875         }
876 
877         if (thumbnails.size() != fullImages.size()) {
878             throw new ProductEntryScreenshotsException();
879         }
880         else {
881             Iterator<byte[]> itr = thumbnails.iterator();
882 
883             while (itr.hasNext()) {
884                 if (itr.next() == null) {
885                     throw new ProductEntryScreenshotsException();
886                 }
887             }
888 
889             itr = fullImages.iterator();
890 
891             while (itr.hasNext()) {
892                 if (itr.next() == null) {
893                     throw new ProductEntryScreenshotsException();
894                 }
895             }
896         }
897     }
898 
899     private static Log _log =
900         LogFactory.getLog(SCProductEntryLocalServiceImpl.class);
901 
902 }