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