001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.softwarecatalog.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.plugin.Version;
020    import com.liferay.portal.kernel.search.Indexable;
021    import com.liferay.portal.kernel.search.IndexableType;
022    import com.liferay.portal.kernel.util.OrderByComparator;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.Time;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.kernel.workflow.WorkflowConstants;
028    import com.liferay.portal.kernel.xml.Document;
029    import com.liferay.portal.kernel.xml.Element;
030    import com.liferay.portal.kernel.xml.SAXReaderUtil;
031    import com.liferay.portal.model.ResourceConstants;
032    import com.liferay.portal.model.User;
033    import com.liferay.portal.plugin.ModuleId;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.util.PropsValues;
036    import com.liferay.portal.webserver.WebServerServletTokenUtil;
037    import com.liferay.portlet.softwarecatalog.DuplicateProductEntryModuleIdException;
038    import com.liferay.portlet.softwarecatalog.ProductEntryAuthorException;
039    import com.liferay.portlet.softwarecatalog.ProductEntryLicenseException;
040    import com.liferay.portlet.softwarecatalog.ProductEntryNameException;
041    import com.liferay.portlet.softwarecatalog.ProductEntryPageURLException;
042    import com.liferay.portlet.softwarecatalog.ProductEntryScreenshotsException;
043    import com.liferay.portlet.softwarecatalog.ProductEntryShortDescriptionException;
044    import com.liferay.portlet.softwarecatalog.ProductEntryTypeException;
045    import com.liferay.portlet.softwarecatalog.model.SCFrameworkVersion;
046    import com.liferay.portlet.softwarecatalog.model.SCLicense;
047    import com.liferay.portlet.softwarecatalog.model.SCProductEntry;
048    import com.liferay.portlet.softwarecatalog.model.SCProductScreenshot;
049    import com.liferay.portlet.softwarecatalog.model.SCProductVersion;
050    import com.liferay.portlet.softwarecatalog.service.base.SCProductEntryLocalServiceBaseImpl;
051    import com.liferay.util.xml.DocUtil;
052    
053    import java.util.Date;
054    import java.util.List;
055    import java.util.Map;
056    import java.util.Properties;
057    
058    /**
059     * @author Jorge Ferrer
060     * @author Brian Wing Shun Chan
061     * @author Raymond Aug??
062     */
063    public class SCProductEntryLocalServiceImpl
064            extends SCProductEntryLocalServiceBaseImpl {
065    
066            @Indexable(type = IndexableType.REINDEX)
067            @Override
068            public SCProductEntry addProductEntry(
069                            long userId, String name, String type, String tags,
070                            String shortDescription, String longDescription, String pageURL,
071                            String author, String repoGroupId, String repoArtifactId,
072                            long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages,
073                            ServiceContext serviceContext)
074                    throws PortalException, SystemException {
075    
076                    // Product entry
077    
078                    User user = userPersistence.findByPrimaryKey(userId);
079                    long groupId = serviceContext.getScopeGroupId();
080                    tags = getTags(tags);
081                    repoGroupId = StringUtil.toLowerCase(repoGroupId.trim());
082                    repoArtifactId = StringUtil.toLowerCase(repoArtifactId.trim());
083                    Date now = new Date();
084    
085                    validate(
086                            0, name, type, shortDescription, pageURL, author, repoGroupId,
087                            repoArtifactId, licenseIds, thumbnails, fullImages);
088    
089                    long productEntryId = counterLocalService.increment();
090    
091                    SCProductEntry productEntry = scProductEntryPersistence.create(
092                            productEntryId);
093    
094                    productEntry.setGroupId(groupId);
095                    productEntry.setCompanyId(user.getCompanyId());
096                    productEntry.setUserId(user.getUserId());
097                    productEntry.setUserName(user.getFullName());
098                    productEntry.setCreateDate(now);
099                    productEntry.setModifiedDate(now);
100                    productEntry.setName(name);
101                    productEntry.setType(type);
102                    productEntry.setTags(tags);
103                    productEntry.setShortDescription(shortDescription);
104                    productEntry.setLongDescription(longDescription);
105                    productEntry.setPageURL(pageURL);
106                    productEntry.setAuthor(author);
107                    productEntry.setRepoGroupId(repoGroupId);
108                    productEntry.setRepoArtifactId(repoArtifactId);
109    
110                    scProductEntryPersistence.update(productEntry);
111    
112                    // Resources
113    
114                    if (serviceContext.isAddGroupPermissions() ||
115                            serviceContext.isAddGuestPermissions()) {
116    
117                            addProductEntryResources(
118                                    productEntry, serviceContext.isAddGroupPermissions(),
119                                    serviceContext.isAddGuestPermissions());
120                    }
121                    else {
122                            addProductEntryResources(
123                                    productEntry, serviceContext.getGroupPermissions(),
124                                    serviceContext.getGuestPermissions());
125                    }
126    
127                    // Licenses
128    
129                    scProductEntryPersistence.setSCLicenses(productEntryId, licenseIds);
130    
131                    // Product screenshots
132    
133                    saveProductScreenshots(productEntry, thumbnails, fullImages);
134    
135                    // Message boards
136    
137                    if (PropsValues.SC_PRODUCT_COMMENTS_ENABLED) {
138                            mbMessageLocalService.addDiscussionMessage(
139                                    userId, productEntry.getUserName(), groupId,
140                                    SCProductEntry.class.getName(), productEntryId,
141                                    WorkflowConstants.ACTION_PUBLISH);
142                    }
143    
144                    return productEntry;
145            }
146    
147            @Override
148            public void addProductEntryResources(
149                            long productEntryId, boolean addGroupPermissions,
150                            boolean addGuestPermissions)
151                    throws PortalException, SystemException {
152    
153                    SCProductEntry productEntry =
154                            scProductEntryPersistence.findByPrimaryKey(productEntryId);
155    
156                    addProductEntryResources(
157                            productEntry, addGroupPermissions, addGuestPermissions);
158            }
159    
160            @Override
161            public void addProductEntryResources(
162                            long productEntryId, String[] groupPermissions,
163                            String[] guestPermissions)
164                    throws PortalException, SystemException {
165    
166                    SCProductEntry productEntry =
167                            scProductEntryPersistence.findByPrimaryKey(productEntryId);
168    
169                    addProductEntryResources(
170                            productEntry, groupPermissions, guestPermissions);
171            }
172    
173            @Override
174            public void addProductEntryResources(
175                            SCProductEntry productEntry, boolean addGroupPermissions,
176                            boolean addGuestPermissions)
177                    throws PortalException, SystemException {
178    
179                    resourceLocalService.addResources(
180                            productEntry.getCompanyId(), productEntry.getGroupId(),
181                            productEntry.getUserId(), SCProductEntry.class.getName(),
182                            productEntry.getProductEntryId(), false, addGroupPermissions,
183                            addGuestPermissions);
184            }
185    
186            @Override
187            public void addProductEntryResources(
188                            SCProductEntry productEntry, String[] groupPermissions,
189                            String[] guestPermissions)
190                    throws PortalException, SystemException {
191    
192                    resourceLocalService.addModelResources(
193                            productEntry.getCompanyId(), productEntry.getGroupId(),
194                            productEntry.getUserId(), SCProductEntry.class.getName(),
195                            productEntry.getProductEntryId(), groupPermissions,
196                            guestPermissions);
197            }
198    
199            @Override
200            public void deleteProductEntries(long groupId)
201                    throws PortalException, SystemException {
202    
203                    List<SCProductEntry> productEntries =
204                            scProductEntryPersistence.findByGroupId(groupId);
205    
206                    for (SCProductEntry productEntry : productEntries) {
207                            scProductEntryLocalService.deleteProductEntry(productEntry);
208                    }
209            }
210    
211            @Indexable(type = IndexableType.DELETE)
212            @Override
213            public SCProductEntry deleteProductEntry(long productEntryId)
214                    throws PortalException, SystemException {
215    
216                    SCProductEntry productEntry =
217                            scProductEntryPersistence.findByPrimaryKey(productEntryId);
218    
219                    return deleteProductEntry(productEntry);
220            }
221    
222            @Indexable(type = IndexableType.DELETE)
223            @Override
224            public SCProductEntry deleteProductEntry(SCProductEntry productEntry)
225                    throws PortalException, SystemException {
226    
227                    // Product entry
228    
229                    scProductEntryPersistence.remove(productEntry);
230    
231                    // Resources
232    
233                    resourceLocalService.deleteResource(
234                            productEntry.getCompanyId(), SCProductEntry.class.getName(),
235                            ResourceConstants.SCOPE_INDIVIDUAL,
236                            productEntry.getProductEntryId());
237    
238                    // Subscriptions
239    
240                    subscriptionLocalService.deleteSubscriptions(
241                            productEntry.getCompanyId(), SCProductEntry.class.getName(),
242                            productEntry.getProductEntryId());
243    
244                    // Product screenshots
245    
246                    scProductScreenshotLocalService.deleteProductScreenshots(
247                            productEntry.getProductEntryId());
248    
249                    // Product versions
250    
251                    scProductVersionLocalService.deleteProductVersions(
252                            productEntry.getProductEntryId());
253    
254                    // Message boards
255    
256                    mbMessageLocalService.deleteDiscussionMessages(
257                            SCProductEntry.class.getName(), productEntry.getProductEntryId());
258    
259                    // Ratings
260    
261                    ratingsStatsLocalService.deleteStats(
262                            SCProductEntry.class.getName(), productEntry.getProductEntryId());
263    
264                    return productEntry;
265            }
266    
267            @Override
268            public List<SCProductEntry> getCompanyProductEntries(
269                            long companyId, int start, int end)
270                    throws SystemException {
271    
272                    return scProductEntryPersistence.findByCompanyId(companyId, start, end);
273            }
274    
275            @Override
276            public int getCompanyProductEntriesCount(long companyId)
277                    throws SystemException {
278    
279                    return scProductEntryPersistence.countByCompanyId(companyId);
280            }
281    
282            @Override
283            public List<SCProductEntry> getProductEntries(
284                            long groupId, int start, int end)
285                    throws SystemException {
286    
287                    return scProductEntryPersistence.findByGroupId(groupId, start, end);
288            }
289    
290            @Override
291            public List<SCProductEntry> getProductEntries(
292                            long groupId, int start, int end, OrderByComparator obc)
293                    throws SystemException {
294    
295                    return scProductEntryPersistence.findByGroupId(
296                            groupId, start, end, obc);
297            }
298    
299            @Override
300            public List<SCProductEntry> getProductEntries(
301                            long groupId, long userId, int start, int end)
302                    throws SystemException {
303    
304                    return scProductEntryPersistence.findByG_U(groupId, userId, start, end);
305            }
306    
307            @Override
308            public List<SCProductEntry> getProductEntries(
309                            long groupId, long userId, int start, int end,
310                            OrderByComparator obc)
311                    throws SystemException {
312    
313                    return scProductEntryPersistence.findByG_U(
314                            groupId, userId, start, end, obc);
315            }
316    
317            @Override
318            public int getProductEntriesCount(long groupId) throws SystemException {
319                    return scProductEntryPersistence.countByGroupId(groupId);
320            }
321    
322            @Override
323            public int getProductEntriesCount(long groupId, long userId)
324                    throws SystemException {
325    
326                    return scProductEntryPersistence.countByG_U(groupId, userId);
327            }
328    
329            @Override
330            public SCProductEntry getProductEntry(long productEntryId)
331                    throws PortalException, SystemException {
332    
333                    return scProductEntryPersistence.findByPrimaryKey(productEntryId);
334            }
335    
336            @Override
337            public String getRepositoryXML(
338                            long groupId, String baseImageURL, Date oldestDate,
339                            int maxNumOfVersions, Properties repoSettings)
340                    throws SystemException {
341    
342                    return getRepositoryXML(
343                            groupId, null, baseImageURL, oldestDate, maxNumOfVersions,
344                            repoSettings);
345            }
346    
347            @Override
348            public String getRepositoryXML(
349                            long groupId, String version, String baseImageURL, Date oldestDate,
350                            int maxNumOfVersions, Properties repoSettings)
351                    throws SystemException {
352    
353                    Document doc = SAXReaderUtil.createDocument();
354    
355                    doc.setXMLEncoding(StringPool.UTF8);
356    
357                    Element root = doc.addElement("plugin-repository");
358    
359                    Element settingsEl = root.addElement("settings");
360    
361                    populateSettingsElement(settingsEl, repoSettings);
362    
363                    List<SCProductEntry> productEntries =
364                            scProductEntryPersistence.findByGroupId(groupId);
365    
366                    for (SCProductEntry productEntry : productEntries) {
367                            if (Validator.isNull(productEntry.getRepoGroupId()) ||
368                                    Validator.isNull(productEntry.getRepoArtifactId())) {
369    
370                                    continue;
371                            }
372    
373                            List<SCProductVersion> productVersions =
374                                    scProductVersionPersistence.findByProductEntryId(
375                                            productEntry.getProductEntryId());
376    
377                            for (int i = 0; i < productVersions.size(); i++) {
378                                    SCProductVersion productVersion = productVersions.get(i);
379    
380                                    if ((maxNumOfVersions > 0) && (maxNumOfVersions < (i + 1))) {
381                                            break;
382                                    }
383    
384                                    if (!productVersion.isRepoStoreArtifact()) {
385                                            continue;
386                                    }
387    
388                                    if ((oldestDate != null) &&
389                                            oldestDate.after(productVersion.getModifiedDate())) {
390    
391                                            continue;
392                                    }
393    
394                                    if (Validator.isNotNull(version) &&
395                                            !isVersionSupported(
396                                                    version, productVersion.getFrameworkVersions())) {
397    
398                                            continue;
399                                    }
400    
401                                    Element el = root.addElement("plugin-package");
402    
403                                    populatePluginPackageElement(
404                                            el, productEntry, productVersion, baseImageURL);
405                            }
406                    }
407    
408                    return doc.asXML();
409            }
410    
411            @Indexable(type = IndexableType.REINDEX)
412            @Override
413            public SCProductEntry updateProductEntry(
414                            long productEntryId, String name, String type, String tags,
415                            String shortDescription, String longDescription, String pageURL,
416                            String author, String repoGroupId, String repoArtifactId,
417                            long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages)
418                    throws PortalException, SystemException {
419    
420                    // Product entry
421    
422                    tags = getTags(tags);
423                    repoGroupId = StringUtil.toLowerCase(repoGroupId.trim());
424                    repoArtifactId = StringUtil.toLowerCase(repoArtifactId.trim());
425                    Date now = new Date();
426    
427                    validate(
428                            productEntryId, name, type, shortDescription, pageURL, author,
429                            repoGroupId, repoArtifactId, licenseIds, thumbnails, fullImages);
430    
431                    SCProductEntry productEntry =
432                            scProductEntryPersistence.findByPrimaryKey(productEntryId);
433    
434                    productEntry.setModifiedDate(now);
435                    productEntry.setName(name);
436                    productEntry.setType(type);
437                    productEntry.setTags(tags);
438                    productEntry.setShortDescription(shortDescription);
439                    productEntry.setLongDescription(longDescription);
440                    productEntry.setPageURL(pageURL);
441                    productEntry.setAuthor(author);
442                    productEntry.setRepoGroupId(repoGroupId);
443                    productEntry.setRepoArtifactId(repoArtifactId);
444    
445                    scProductEntryPersistence.update(productEntry);
446    
447                    // Licenses
448    
449                    scProductEntryPersistence.setSCLicenses(productEntryId, licenseIds);
450    
451                    // Product screenshots
452    
453                    if (thumbnails.size() == 0) {
454                            scProductScreenshotLocalService.deleteProductScreenshots(
455                                    productEntryId);
456                    }
457                    else {
458                            saveProductScreenshots(productEntry, thumbnails, fullImages);
459                    }
460    
461                    return productEntry;
462            }
463    
464            protected String getTags(String tags) {
465                    tags = StringUtil.toLowerCase(tags.trim());
466    
467                    return StringUtil.merge(StringUtil.split(tags), ", ");
468            }
469    
470            protected boolean isVersionSupported(
471                    String version, List<SCFrameworkVersion> frameworkVersions) {
472    
473                    Version currentVersion = Version.getInstance(version);
474    
475                    for (SCFrameworkVersion frameworkVersion : frameworkVersions) {
476                            Version supportedVersion = Version.getInstance(
477                                    frameworkVersion.getName());
478    
479                            if (supportedVersion.includes(currentVersion)) {
480                                    return true;
481                            }
482                    }
483    
484                    return false;
485            }
486    
487            protected void populatePluginPackageElement(
488                            Element el, SCProductEntry productEntry,
489                            SCProductVersion productVersion, String baseImageURL)
490                    throws SystemException {
491    
492                    DocUtil.add(el, "name", productEntry.getName());
493    
494                    String moduleId = ModuleId.toString(
495                            productEntry.getRepoGroupId(), productEntry.getRepoArtifactId(),
496                            productVersion.getVersion(), "war");
497    
498                    DocUtil.add(el, "module-id", moduleId);
499    
500                    DocUtil.add(
501                            el, "modified-date",
502                            Time.getRFC822(productVersion.getModifiedDate()));
503    
504                    Element typesEl = el.addElement("types");
505    
506                    DocUtil.add(typesEl, "type", productEntry.getType());
507    
508                    Element tagsEl = el.addElement("tags");
509    
510                    String[] tags = StringUtil.split(productEntry.getTags());
511    
512                    for (int i = 0; i < tags.length; i++) {
513                            DocUtil.add(tagsEl, "tag", tags[i]);
514                    }
515    
516                    DocUtil.add(
517                            el, "short-description", productEntry.getShortDescription());
518    
519                    if (Validator.isNotNull(productEntry.getLongDescription())) {
520                            DocUtil.add(
521                                    el, "long-description", productEntry.getLongDescription());
522                    }
523    
524                    if (Validator.isNotNull(productVersion.getChangeLog())) {
525                            DocUtil.add(el, "change-log", productVersion.getChangeLog());
526                    }
527    
528                    if (Validator.isNotNull(productVersion.getDirectDownloadURL())) {
529                            DocUtil.add(
530                                    el, "download-url", productVersion.getDirectDownloadURL());
531                    }
532    
533                    DocUtil.add(el, "author", productEntry.getAuthor());
534    
535                    Element screenshotsEl = el.addElement("screenshots");
536    
537                    for (SCProductScreenshot screenshot : productEntry.getScreenshots()) {
538                            long thumbnailId = screenshot.getThumbnailId();
539                            long fullImageId = screenshot.getFullImageId();
540    
541                            Element screenshotEl = screenshotsEl.addElement("screenshot");
542    
543                            DocUtil.add(
544                                    screenshotEl, "thumbnail-url",
545                                    baseImageURL + "?img_id=" + thumbnailId + "&t=" +
546                                            WebServerServletTokenUtil.getToken(thumbnailId));
547                            DocUtil.add(
548                                    screenshotEl, "large-image-url",
549                                    baseImageURL + "?img_id=" + fullImageId + "&t=" +
550                                            WebServerServletTokenUtil.getToken(fullImageId));
551                    }
552    
553                    Element licensesEl = el.addElement("licenses");
554    
555                    for (SCLicense license : productEntry.getLicenses()) {
556                            Element licenseEl = licensesEl.addElement("license");
557    
558                            licenseEl.addText(license.getName());
559                            licenseEl.addAttribute(
560                                    "osi-approved", String.valueOf(license.isOpenSource()));
561                    }
562    
563                    Element liferayVersionsEl = el.addElement("liferay-versions");
564    
565                    for (SCFrameworkVersion frameworkVersion :
566                                    productVersion.getFrameworkVersions()) {
567    
568                            DocUtil.add(
569                                    liferayVersionsEl, "liferay-version",
570                                    frameworkVersion.getName());
571                    }
572            }
573    
574            protected void populateSettingsElement(
575                    Element el, Properties repoSettings) {
576    
577                    if (repoSettings == null) {
578                            return;
579                    }
580    
581                    for (Map.Entry<Object, Object> entry : repoSettings.entrySet()) {
582                            String name = (String)entry.getKey();
583                            String value = (String)entry.getValue();
584    
585                            Element settingEl = el.addElement("setting");
586    
587                            settingEl.addAttribute("name", name);
588                            settingEl.addAttribute("value", value);
589                    }
590            }
591    
592            protected void saveProductScreenshots(
593                            SCProductEntry productEntry, List<byte[]> thumbnails,
594                            List<byte[]> fullImages)
595                    throws PortalException, SystemException {
596    
597                    long productEntryId = productEntry.getProductEntryId();
598    
599                    List<SCProductScreenshot> productScreenshots =
600                            scProductScreenshotPersistence.findByProductEntryId(productEntryId);
601    
602                    if (thumbnails.size() < productScreenshots.size()) {
603                            for (int i = thumbnails.size(); i < productScreenshots.size();
604                                            i++) {
605    
606                                    SCProductScreenshot productScreenshot = productScreenshots.get(
607                                            i);
608    
609                                    scProductScreenshotLocalService.deleteProductScreenshot(
610                                            productScreenshot);
611                            }
612                    }
613    
614                    for (int i = 0; i < thumbnails.size(); i++) {
615                            int priority = i;
616    
617                            byte[] thumbnail = thumbnails.get(i);
618                            byte[] fullImage = fullImages.get(i);
619    
620                            SCProductScreenshot productScreenshot =
621                                    scProductScreenshotPersistence.fetchByP_P(
622                                            productEntryId, priority);
623    
624                            if (productScreenshot == null) {
625                                    long productScreenshotId = counterLocalService.increment();
626    
627                                    productScreenshot = scProductScreenshotPersistence.create(
628                                            productScreenshotId);
629    
630                                    productScreenshot.setCompanyId(productEntry.getCompanyId());
631                                    productScreenshot.setGroupId(productEntry.getGroupId());
632                                    productScreenshot.setProductEntryId(productEntryId);
633                                    productScreenshot.setThumbnailId(
634                                            counterLocalService.increment());
635                                    productScreenshot.setFullImageId(
636                                            counterLocalService.increment());
637                                    productScreenshot.setPriority(priority);
638    
639                                    scProductScreenshotPersistence.update(productScreenshot);
640                            }
641    
642                            imageLocalService.updateImage(
643                                    productScreenshot.getThumbnailId(), thumbnail);
644                            imageLocalService.updateImage(
645                                    productScreenshot.getFullImageId(), fullImage);
646                    }
647            }
648    
649            protected void validate(
650                            long productEntryId, String name, String type,
651                            String shortDescription, String pageURL, String author,
652                            String repoGroupId, String repoArtifactId, long[] licenseIds,
653                            List<byte[]> thumbnails, List<byte[]> fullImages)
654                    throws PortalException, SystemException {
655    
656                    if (Validator.isNull(name)) {
657                            throw new ProductEntryNameException();
658                    }
659    
660                    if (Validator.isNull(type)) {
661                            throw new ProductEntryTypeException();
662                    }
663    
664                    if (Validator.isNull(shortDescription)) {
665                            throw new ProductEntryShortDescriptionException();
666                    }
667    
668                    if (Validator.isNull(pageURL)) {
669                            throw new ProductEntryPageURLException();
670                    }
671                    else if (!Validator.isUrl(pageURL)) {
672                            throw new ProductEntryPageURLException();
673                    }
674    
675                    if (Validator.isNull(author)) {
676                            throw new ProductEntryAuthorException();
677                    }
678    
679                    SCProductEntry productEntry = scProductEntryPersistence.fetchByRG_RA(
680                            repoGroupId, repoArtifactId);
681    
682                    if ((productEntry != null) &&
683                            (productEntry.getProductEntryId() != productEntryId)) {
684    
685                            throw new DuplicateProductEntryModuleIdException(
686                                    "{productEntryId=" + productEntryId + "}");
687                    }
688    
689                    if (licenseIds.length == 0) {
690                            throw new ProductEntryLicenseException();
691                    }
692    
693                    if (thumbnails.size() != fullImages.size()) {
694                            throw new ProductEntryScreenshotsException();
695                    }
696                    else {
697                            for (byte[] thumbnail : thumbnails) {
698                                    if (thumbnail == null) {
699                                            throw new ProductEntryScreenshotsException();
700                                    }
701                            }
702    
703                            for (byte[] fullImage : fullImages) {
704                                    if (fullImage == null) {
705                                            throw new ProductEntryScreenshotsException();
706                                    }
707                            }
708                    }
709            }
710    
711    }