1
22
23 package com.liferay.portal.plugin;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.plugin.PluginPackage;
28 import com.liferay.portal.kernel.plugin.RemotePluginPackageRepository;
29 import com.liferay.portal.kernel.search.Hits;
30 import com.liferay.portal.kernel.util.ArrayUtil;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.StringMaker;
33 import com.liferay.portal.kernel.util.StringPool;
34 import com.liferay.portal.kernel.util.StringUtil;
35 import com.liferay.portal.kernel.util.Validator;
36 import com.liferay.portal.lucene.LuceneFields;
37 import com.liferay.portal.lucene.LuceneUtil;
38 import com.liferay.portal.model.impl.CompanyImpl;
39 import com.liferay.portal.util.PortalUtil;
40 import com.liferay.portal.util.PrefsPropsUtil;
41 import com.liferay.portal.util.PropsUtil;
42 import com.liferay.portal.util.PropsValues;
43 import com.liferay.portal.util.ReleaseInfo;
44 import com.liferay.util.Html;
45 import com.liferay.util.Http;
46 import com.liferay.util.License;
47 import com.liferay.util.Screenshot;
48 import com.liferay.util.Time;
49 import com.liferay.util.Version;
50 import com.liferay.util.lucene.HitsImpl;
51
52 import java.io.IOException;
53
54 import java.net.MalformedURLException;
55
56 import java.text.DateFormat;
57 import java.text.SimpleDateFormat;
58
59 import java.util.ArrayList;
60 import java.util.Arrays;
61 import java.util.Collection;
62 import java.util.Date;
63 import java.util.HashMap;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Locale;
67 import java.util.Map;
68 import java.util.Properties;
69 import java.util.Set;
70 import java.util.TreeSet;
71
72 import org.apache.commons.httpclient.HostConfiguration;
73 import org.apache.commons.httpclient.HttpClient;
74 import org.apache.commons.httpclient.methods.GetMethod;
75 import org.apache.commons.lang.time.StopWatch;
76 import org.apache.commons.logging.Log;
77 import org.apache.commons.logging.LogFactory;
78 import org.apache.lucene.index.IndexWriter;
79 import org.apache.lucene.index.Term;
80 import org.apache.lucene.search.BooleanClause;
81 import org.apache.lucene.search.BooleanQuery;
82 import org.apache.lucene.search.Query;
83 import org.apache.lucene.search.Searcher;
84 import org.apache.lucene.search.TermQuery;
85
86 import org.dom4j.Attribute;
87 import org.dom4j.Document;
88 import org.dom4j.DocumentException;
89 import org.dom4j.Element;
90
91
98 public class PluginPackageUtil {
99
100 public static final String REPOSITORY_XML_FILENAME_PREFIX =
101 "liferay-plugin-repository";
102
103 public static final String REPOSITORY_XML_FILENAME_EXTENSION =
104 "xml";
105
106 public static void endPluginPackageInstallation(String preliminaryContext) {
107 _instance._endPluginPackageInstallation(preliminaryContext);
108 }
109
110 public static List getAllAvailablePluginPackages()
111 throws PluginPackageException {
112
113 return _instance._getAllAvailablePluginPackages();
114 }
115
116 public static Collection getAvailableTags() {
117 return _instance._getAvailableTags();
118 }
119
120 public static List getInstalledPluginPackages() {
121 return _instance._getInstalledPluginPackages();
122 }
123
124 public static PluginPackage getLatestAvailablePluginPackage(
125 String groupId, String artifactId)
126 throws SystemException {
127
128 return _instance._getLatestAvailablePluginPackage(groupId, artifactId);
129 }
130
131 public static PluginPackage getLatestInstalledPluginPackage(
132 String groupId, String artifactId) {
133
134 return _instance._getLatestInstalledPluginPackage(groupId, artifactId);
135 }
136
137 public static Date getLastUpdateDate() {
138 return _instance._getLastUpdateDate();
139 }
140
141 public static PluginPackage getPluginPackageByModuleId(
142 String moduleId, String repositoryURL)
143 throws DocumentException, IOException, PluginPackageException {
144
145 return _instance._getPluginPackageByModuleId(moduleId, repositoryURL);
146 }
147
148 public static PluginPackage getPluginPackageByURL(String url)
149 throws PluginPackageException {
150
151 return _instance._getPluginPackageByURL(url);
152 }
153
154 public static RemotePluginPackageRepository getRepository(
155 String repositoryURL)
156 throws PluginPackageException {
157
158 return _instance._getRepository(repositoryURL);
159 }
160
161 public static String[] getRepositoryURLs() throws PluginPackageException {
162 return _instance._getRepositoryURLs();
163 }
164
165 public static String[] getSupportedTypes() {
166 return _instance._getSupportedTypes();
167 }
168
169 public static boolean isCurrentVersionSupported(List versions) {
170 return _instance._isCurrentVersionSupported(versions);
171 }
172
173 public static boolean isIgnored(PluginPackage pluginPackage)
174 throws PortalException, SystemException {
175
176 return _instance._isIgnored(pluginPackage);
177 }
178
179 public static boolean isInstallationInProcess(String context) {
180 return _instance._isInstallationInProcess(context);
181 }
182
183 public static boolean isTrusted(String repositoryURL)
184 throws PluginPackageException {
185
186 return _instance._isTrusted(repositoryURL);
187 }
188
189 public static boolean isUpdateAvailable()
190 throws PortalException, SystemException {
191
192 return _instance._isUpdateAvailable();
193 }
194
195 public static PluginPackage readPluginPackageProps(
196 String displayName, Properties props) {
197
198 return _instance._readPluginPackageProps(displayName, props);
199 }
200
201 public static PluginPackage readPluginPackageXml(String xml)
202 throws DocumentException {
203
204 return _instance._readPluginPackageXml(xml);
205 }
206
207 public static PluginPackage readPluginPackageXml(Element pluginPackageEl) {
208 return _instance._readPluginPackageXml(pluginPackageEl);
209 }
210
211 public static void refreshUpdatesAvailableCache() {
212 _instance._refreshUpdatesAvailableCache();
213 }
214
215 public static void reIndex() throws SystemException {
216 _instance._reIndex();
217 }
218
219 public static RepositoryReport reloadRepositories() throws SystemException {
220 return _instance._reloadRepositories();
221 }
222
223 public static void registerInstalledPluginPackage(
224 PluginPackage pluginPackage) {
225
226 _instance._registerInstalledPluginPackage(pluginPackage);
227 }
228
229 public static void registerPluginPackageInstallation(
230 String preliminaryContext) {
231
232 _instance._registerPluginPackageInstallation(preliminaryContext);
233 }
234
235 public static Hits search(
236 String keywords, String type, String tag, String license,
237 String repositoryURL, String status)
238 throws SystemException {
239
240 return _instance._search(
241 keywords, type, tag, license, repositoryURL, status);
242 }
243
244 public static void unregisterInstalledPluginPackage(
245 PluginPackage pluginPackage) {
246
247 _instance._unregisterInstalledPluginPackage(pluginPackage);
248 }
249
250 public static void updateInstallingPluginPackage(
251 String preliminaryContext, PluginPackage pluginPackage) {
252
253 _instance._updateInstallingPluginPackage(
254 preliminaryContext, pluginPackage);
255 }
256
257 private PluginPackageUtil() {
258 _installedPluginPackages = new LocalPluginPackageRepository();
259 _repositoryCache = new HashMap();
260 _availableTagsCache = new TreeSet();
261 }
262
263 private void _checkRepositories(String repositoryURL)
264 throws PluginPackageException {
265
266 String[] repositoryURLs = null;
267
268 if (Validator.isNotNull(repositoryURL)) {
269 repositoryURLs = new String[] {repositoryURL};
270 }
271 else {
272 repositoryURLs = _getRepositoryURLs();
273 }
274
275 for (int i = 0; i < repositoryURLs.length; i++) {
276 _getRepository(repositoryURLs[i]);
277 }
278 }
279
280 private void _endPluginPackageInstallation(String preliminaryContext) {
281 _installedPluginPackages.unregisterPluginPackageInstallation(
282 preliminaryContext);
283 }
284
285 private PluginPackage _findLatestVersion(List pluginPackages) {
286 PluginPackage pluginPackage = null;
287
288 Iterator itr = pluginPackages.iterator();
289
290 while (itr.hasNext()) {
291 PluginPackage curPluginPackage = (PluginPackage)itr.next();
292
293 if ((pluginPackage == null) ||
294 (curPluginPackage.isLaterVersionThan(pluginPackage))) {
295
296 pluginPackage = curPluginPackage;
297 }
298 }
299
300 return pluginPackage;
301 }
302
303 private List _getAllAvailablePluginPackages()
304 throws PluginPackageException {
305
306 List plugins = new ArrayList();
307
308 String[] repositoryURLs = _getRepositoryURLs();
309
310 for (int i = 0; i < repositoryURLs.length; i++) {
311 try {
312 RemotePluginPackageRepository repository =
313 _getRepository(repositoryURLs[i]);
314
315 plugins.addAll(repository.getPluginPackages());
316 }
317 catch(PluginPackageException ppe) {
318 String message = ppe.getMessage();
319
320 if (message.startsWith("Unable to communicate")) {
321 if (_log.isWarnEnabled()) {
322 _log.warn(message);
323 }
324 }
325 else {
326 _log.error(message);
327 }
328 }
329 }
330
331 return plugins;
332 }
333
334 private Collection _getAvailableTags() {
335 return _availableTagsCache;
336 }
337
338 private List _getInstalledPluginPackages() {
339 return _installedPluginPackages.getSortedPluginPackages();
340 }
341
342 private PluginPackage _getLatestAvailablePluginPackage(
343 String groupId, String artifactId)
344 throws SystemException {
345
346 List pluginPackages = new ArrayList();
347
348 String[] repositoryURLs = _getRepositoryURLs();
349
350 for (int i = 0; i < repositoryURLs.length; i++) {
351 RemotePluginPackageRepository repository =
352 _getRepository(repositoryURLs[i]);
353
354 List curPluginPackages =
355 repository.findPluginsByGroupIdAndArtifactId(
356 groupId, artifactId);
357
358 if (curPluginPackages != null) {
359 pluginPackages.addAll(curPluginPackages);
360 }
361 }
362
363 return _findLatestVersion(pluginPackages);
364 }
365
366 private PluginPackage _getLatestInstalledPluginPackage(
367 String groupId, String artifactId) {
368
369 return _installedPluginPackages.getLatestPluginPackage(
370 groupId, artifactId);
371 }
372
373 private Date _getLastUpdateDate() {
374 return _lastUpdateDate;
375 }
376
377 private PluginPackage _getPluginPackageByModuleId(
378 String moduleId, String repositoryURL)
379 throws DocumentException, IOException, PluginPackageException {
380
381 RemotePluginPackageRepository repository = _getRepository(
382 repositoryURL);
383
384 return repository.findPluginPackageByModuleId(moduleId);
385 }
386
387 private PluginPackage _getPluginPackageByURL(String url)
388 throws PluginPackageException {
389
390 String[] repositoryURLs = _getRepositoryURLs();
391
392 for (int i = 0; i < repositoryURLs.length; i++) {
393 String repositoryURL = repositoryURLs[i];
394
395 try {
396 RemotePluginPackageRepository repository =
397 _getRepository(repositoryURL);
398
399 return repository.findPluginByArtifactURL(url);
400 }
401 catch (PluginPackageException pe) {
402 _log.error("Unable to load repository " + repositoryURL, pe);
403 }
404 }
405
406 return null;
407 }
408
409 private RemotePluginPackageRepository _getRepository(
410 String repositoryURL)
411 throws PluginPackageException {
412
413 RemotePluginPackageRepository repository =
414 (RemotePluginPackageRepository)_repositoryCache.get(repositoryURL);
415
416 if (repository != null) {
417 return repository;
418 }
419
420 return _loadRepository(repositoryURL);
421 }
422
423 private String[] _getRepositoryURLs() throws PluginPackageException {
424 try {
425 String[] trusted = PrefsPropsUtil.getStringArray(
426 PropsUtil.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
427 PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
428 String[] untrusted = PrefsPropsUtil.getStringArray(
429 PropsUtil.PLUGIN_REPOSITORIES_UNTRUSTED, StringPool.NEW_LINE,
430 PropsValues.PLUGIN_REPOSITORIES_UNTRUSTED);
431
432 return ArrayUtil.append(trusted, untrusted);
433 }
434 catch (Exception e) {
435 throw new PluginPackageException(
436 "Unable to read repository list", e);
437 }
438 }
439
440 private String[] _getStatusAndInstalledVersion(
441 PluginPackage pluginPackage) {
442
443 PluginPackage installedPluginPackage =
444 _installedPluginPackages.getLatestPluginPackage(
445 pluginPackage.getGroupId(), pluginPackage.getArtifactId());
446
447 String status = null;
448 String installedVersion = null;
449
450 if (installedPluginPackage == null) {
451 status = PluginPackageImpl.STATUS_NOT_INSTALLED;
452 }
453 else {
454 installedVersion = installedPluginPackage.getVersion();
455
456 if (installedPluginPackage.isLaterVersionThan(pluginPackage)) {
457 status = PluginPackageImpl.STATUS_NEWER_VERSION_INSTALLED;
458 }
459 else if (installedPluginPackage.isPreviousVersionThan(
460 pluginPackage)) {
461
462 status = PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED;
463 }
464 else {
465 status = PluginPackageImpl.STATUS_SAME_VERSION_INSTALLED;
466 }
467 }
468
469 return new String[] {status, installedVersion};
470 }
471
472 private String[] _getSupportedTypes() {
473 return PropsValues.PLUGIN_TYPES;
474 }
475
476 private void _indexPluginPackage(PluginPackage pluginPackage) {
477 String[] statusAndInstalledVersion =
478 _getStatusAndInstalledVersion(pluginPackage);
479
480 String status = statusAndInstalledVersion[0];
481 String installedVersion = statusAndInstalledVersion[1];
482
483 try {
484 PluginPackageIndexer.updatePluginPackage(
485 pluginPackage.getModuleId(), pluginPackage.getName(),
486 pluginPackage.getVersion(), pluginPackage.getModifiedDate(),
487 pluginPackage.getAuthor(), pluginPackage.getTypes(),
488 pluginPackage.getTags(), pluginPackage.getLicenses(),
489 pluginPackage.getLiferayVersions(),
490 pluginPackage.getShortDescription(),
491 pluginPackage.getLongDescription(),
492 pluginPackage.getChangeLog(), pluginPackage.getPageURL(),
493 pluginPackage.getRepositoryURL(), status, installedVersion);
494 }
495 catch (Exception e) {
496 _log.error("Error reindexing " + pluginPackage.getModuleId(), e);
497 }
498 }
499
500 private boolean _isCurrentVersionSupported(List versions) {
501 Version currentVersion = Version.getInstance(ReleaseInfo.getVersion());
502
503 for (int i = 0; i < versions.size(); i++) {
504 Version supportedVersion = Version.getInstance(
505 (String)versions.get(i));
506
507 if (supportedVersion.includes(currentVersion)) {
508 return true;
509 }
510 }
511
512 return false;
513 }
514
515 private boolean _isIgnored(PluginPackage pluginPackage)
516 throws PortalException, SystemException {
517
518 String packageId = pluginPackage.getPackageId();
519
520 String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
521 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
522 StringPool.NEW_LINE,
523 PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
524
525 for (int i = 0; i < pluginPackagesIgnored.length; i++) {
526 String curPluginPackagesIgnored = pluginPackagesIgnored[i];
527
528 if (curPluginPackagesIgnored.endsWith(StringPool.STAR)) {
529 String prefix = curPluginPackagesIgnored.substring(
530 0, curPluginPackagesIgnored.length() - 2);
531
532 if (packageId.startsWith(prefix)) {
533 return true;
534 }
535 }
536 else {
537 if (packageId.equals(curPluginPackagesIgnored)) {
538 return true;
539 }
540 }
541 }
542
543 return false;
544 }
545
546 private boolean _isInstallationInProcess(String context) {
547 if (_installedPluginPackages.getInstallingPluginPackage(
548 context) != null) {
549
550 return true;
551 }
552 else {
553 return false;
554 }
555 }
556
557 private boolean _isTrusted(String repositoryURL)
558 throws PluginPackageException {
559
560 try {
561 String[] trusted = PrefsPropsUtil.getStringArray(
562 PropsUtil.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
563 PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
564
565 if (ArrayUtil.contains(trusted, repositoryURL)) {
566 return true;
567 }
568 else {
569 return false;
570 }
571 }
572 catch (Exception e) {
573 throw new PluginPackageException(
574 "Unable to read repository list", e);
575 }
576 }
577
578 private boolean _isUpdateAvailable()
579 throws PortalException, SystemException {
580
581 if (!PrefsPropsUtil.getBoolean(
582 PropsUtil.PLUGIN_NOTIFICATIONS_ENABLED,
583 PropsValues.PLUGIN_NOTIFICATIONS_ENABLED)) {
584
585 return false;
586 }
587
588 if (_updateAvailable != null) {
589 return _updateAvailable.booleanValue();
590 }
591 else if (!_settingUpdateAvailable) {
592 _settingUpdateAvailable = true;
593
594 Thread indexerThread = new Thread(
595 new UpdateAvailableRunner(), PluginPackageUtil.class.getName());
596
597 indexerThread.setPriority(Thread.MIN_PRIORITY);
598
599 indexerThread.start();
600 }
601
602 return false;
603 }
604
605 private RemotePluginPackageRepository _loadRepository(String repositoryURL)
606 throws PluginPackageException {
607
608 RemotePluginPackageRepository repository = null;
609
610 StringMaker sm = new StringMaker();
611
612 sm.append(repositoryURL);
613 sm.append(StringPool.SLASH);
614 sm.append(REPOSITORY_XML_FILENAME_PREFIX);
615 sm.append(StringPool.DASH);
616 sm.append(ReleaseInfo.getVersion());
617 sm.append(StringPool.PERIOD);
618 sm.append(REPOSITORY_XML_FILENAME_EXTENSION);
619
620 String pluginsXmlURL = sm.toString();
621
622 try {
623 HostConfiguration hostConfig = Http.getHostConfig(pluginsXmlURL);
624
625 HttpClient client = Http.getClient(hostConfig);
626
627 GetMethod getFileMethod = new GetMethod(pluginsXmlURL);
628
629 byte[] bytes = null;
630
631 try {
632 int responseCode = client.executeMethod(
633 hostConfig, getFileMethod);
634
635 if (responseCode != 200) {
636 if (_log.isDebugEnabled()) {
637 _log.debug(
638 "A repository for version " +
639 ReleaseInfo.getVersion() + " was not found. " +
640 "Checking general repository");
641 }
642
643 sm = new StringMaker();
644
645 sm.append(repositoryURL);
646 sm.append(StringPool.SLASH);
647 sm.append(REPOSITORY_XML_FILENAME_PREFIX);
648 sm.append(StringPool.PERIOD);
649 sm.append(REPOSITORY_XML_FILENAME_EXTENSION);
650
651 pluginsXmlURL = sm.toString();
652
653 getFileMethod = new GetMethod(pluginsXmlURL);
654
655 responseCode = client.executeMethod(
656 hostConfig, getFileMethod);
657
658 if (responseCode != 200) {
659 throw new PluginPackageException(
660 "Unable to download file " + pluginsXmlURL +
661 " because of response code " + responseCode);
662 }
663 }
664
665 bytes = getFileMethod.getResponseBody();
666 }
667 finally {
668 getFileMethod.releaseConnection();
669 }
670
671 if ((bytes != null) && (bytes.length > 0)) {
672 repository = _parseRepositoryXml(
673 new String(bytes), repositoryURL);
674
675 _repositoryCache.put(repositoryURL, repository);
676 _availableTagsCache.addAll(repository.getTags());
677 _lastUpdateDate = new Date();
678 _updateAvailable = null;
679
680 return repository;
681 }
682 else {
683 _lastUpdateDate = new Date();
684
685 throw new PluginPackageException("Download returned 0 bytes");
686 }
687 }
688 catch (MalformedURLException mue) {
689 _repositoryCache.remove(repositoryURL);
690
691 throw new PluginPackageException(
692 "Invalid URL " + pluginsXmlURL, mue);
693 }
694 catch (IOException ioe) {
695 _repositoryCache.remove(repositoryURL);
696
697 throw new PluginPackageException(
698 "Unable to communicate with repository " + repositoryURL, ioe);
699 }
700 catch (DocumentException de) {
701 _repositoryCache.remove(repositoryURL);
702
703 throw new PluginPackageException(
704 "Unable to parse plugin list for repository " + repositoryURL,
705 de);
706 }
707 }
708
709 private RemotePluginPackageRepository _parseRepositoryXml(
710 String xml, String repositoryURL)
711 throws DocumentException, IOException {
712
713 List supportedPluginTypes = Arrays.asList(getSupportedTypes());
714
715 if (_log.isDebugEnabled()) {
716 _log.debug(
717 "Loading plugin repository " + repositoryURL + ":\n" + xml);
718 }
719
720 RemotePluginPackageRepository pluginPackageRepository =
721 new RemotePluginPackageRepository(repositoryURL);
722
723 if (xml == null) {
724 return pluginPackageRepository;
725 }
726
727 Document doc = PortalUtil.readDocumentFromXML(xml);
728
729 Element root = doc.getRootElement();
730
731 Properties settings = _readProperties(
732 root.element("settings"), "setting");
733
734 pluginPackageRepository.setSettings(settings);
735
736 Iterator itr1 = root.elements("plugin-package").iterator();
737
738 while (itr1.hasNext()) {
739 Element pluginPackageEl = (Element)itr1.next();
740
741 PluginPackage pluginPackage = _readPluginPackageXml(
742 pluginPackageEl);
743
744 if (!_isCurrentVersionSupported(
745 pluginPackage.getLiferayVersions())) {
746
747 continue;
748 }
749
750 Iterator itr2 = pluginPackage.getTypes().iterator();
751
752 boolean containsSupportedTypes = false;
753
754 while (itr2.hasNext()) {
755 String type = (String)itr2.next();
756
757 if (supportedPluginTypes.contains(type)) {
758 containsSupportedTypes = true;
759
760 break;
761 }
762 }
763
764 if (!containsSupportedTypes) {
765 continue;
766 }
767
768 pluginPackage.setRepository(pluginPackageRepository);
769
770 pluginPackageRepository.addPluginPackage(pluginPackage);
771
772 _indexPluginPackage(pluginPackage);
773 }
774
775 return pluginPackageRepository;
776 }
777
778 private Date _readDate(String text) {
779 if (Validator.isNotNull(text)) {
780 DateFormat dateFormat = new SimpleDateFormat(
781 Time.RFC822_FORMAT, Locale.US);
782
783 try {
784 return dateFormat.parse(text);
785 }
786 catch (Exception e) {
787 if (_log.isWarnEnabled()) {
788 _log.warn("Unable to parse date " + text);
789 }
790 }
791 }
792
793 return new Date();
794 }
795
796 private String _readHtml(String text) {
797 return GetterUtil.getString(text);
798 }
799
800 private List _readLicenseList(Element parent, String childTagName) {
801 List result = new ArrayList();
802
803 Iterator itr = parent.elements(childTagName).iterator();
804
805 while (itr.hasNext()) {
806 Element tagEl = (Element)itr.next();
807
808 License license = new License();
809
810 license.setName(tagEl.getText());
811
812 Attribute osiApproved = tagEl.attribute("osi-approved");
813
814 if (osiApproved != null) {
815 license.setOsiApproved(
816 GetterUtil.getBoolean(osiApproved.getText()));
817 }
818
819 Attribute url = tagEl.attribute("url");
820
821 if (url != null) {
822 license.setUrl(url.getText());
823 }
824
825 result.add(license);
826 }
827
828 return result;
829 }
830
831 private List _readList(Element parent, String childTagName) {
832 List result = new ArrayList();
833
834 if (parent != null) {
835 Iterator itr = parent.elements(childTagName).iterator();
836
837 while (itr.hasNext()) {
838 Element element = (Element)itr.next();
839
840 String text = element.getText().trim().toLowerCase();
841
842 result.add(text);
843 }
844 }
845
846 return result;
847 }
848
849 private PluginPackage _readPluginPackageProps(
850 String displayName, Properties props) {
851
852 int pos = displayName.indexOf("-portlet-");
853
854 String pluginType = "portlet";
855
856 if (pos == -1) {
857 pos = displayName.indexOf("-theme-");
858
859 pluginType = "theme";
860 }
861
862 if (pos == -1) {
863 return null;
864 }
865
866 String displayPrefix = displayName.substring(0, pos);
867
868 String moduleGroupId = GetterUtil.getString(
869 props.getProperty("module-group-id"));
870 String moduleArtifactId = displayPrefix + "-" + pluginType;
871 String moduleVersion = displayName.substring(
872 pos + pluginType.length() + 2);
873 String moduleId =
874 moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
875 "/war";
876
877 String pluginName = GetterUtil.getString(props.getProperty("name"));
878
879 String deploymentContext = GetterUtil.getString(props.getProperty(
880 "recommended-deployment-context"), moduleArtifactId);
881
882 String author = GetterUtil.getString(props.getProperty("author"));
883
884 List types = new ArrayList();
885
886 types.add(pluginType);
887
888 List licenses = new ArrayList();
889
890 String[] licensesArray = StringUtil.split(
891 props.getProperty("licenses"));
892
893 for (int i = 0; i < licensesArray.length; i++) {
894 License license = new License();
895
896 license.setName(licensesArray[i].trim());
897 license.setOsiApproved(true);
898
899 licenses.add(license);
900 }
901
902 List liferayVersions = new ArrayList();
903
904 String[] liferayVersionsArray = StringUtil.split(
905 props.getProperty("liferay-versions"));
906
907 for (int i = 0; i < liferayVersionsArray.length; i++) {
908 liferayVersions.add(liferayVersionsArray[i].trim());
909 }
910
911 if (liferayVersions.size() == 0) {
912 liferayVersions.add(ReleaseInfo.getVersion() + "+");
913 }
914
915 List tags = new ArrayList();
916
917 String[] tagsArray = StringUtil.split(props.getProperty("tags"));
918
919 for (int i = 0; i < tagsArray.length; i++) {
920 tags.add(tagsArray[i].trim());
921 }
922
923 String shortDescription = GetterUtil.getString(
924 props.getProperty("short-description"));
925 String longDescription = GetterUtil.getString(
926 props.getProperty("long-description"));
927 String changeLog = GetterUtil.getString(
928 props.getProperty("change-log"));
929 String pageURL = GetterUtil.getString(props.getProperty("page-url"));
930 String downloadURL = GetterUtil.getString(
931 props.getProperty("download-url"));
932
933 PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
934
935 pluginPackage.setName(pluginName);
936 pluginPackage.setRecommendedDeploymentContext(deploymentContext);
937 pluginPackage.setAuthor(author);
939 pluginPackage.setTypes(types);
940 pluginPackage.setLicenses(licenses);
941 pluginPackage.setLiferayVersions(liferayVersions);
942 pluginPackage.setTags(tags);
943 pluginPackage.setShortDescription(shortDescription);
944 pluginPackage.setLongDescription(longDescription);
945 pluginPackage.setChangeLog(changeLog);
946 pluginPackage.setPageURL(pageURL);
948 pluginPackage.setDownloadURL(downloadURL);
949
951 return pluginPackage;
952 }
953
954 private PluginPackage _readPluginPackageXml(String xml)
955 throws DocumentException {
956
957 Document doc = PortalUtil.readDocumentFromXML(xml);
958
959 Element root = doc.getRootElement();
960
961 return _readPluginPackageXml(root);
962 }
963
964 private PluginPackage _readPluginPackageXml(Element pluginPackageEl) {
965 String name = pluginPackageEl.elementText("name");
966
967 if (_log.isDebugEnabled()) {
968 _log.debug("Reading pluginPackage definition " + name);
969 }
970
971 PluginPackage pluginPackage = new PluginPackageImpl(
972 GetterUtil.getString(pluginPackageEl.elementText("module-id")));
973
974 List liferayVersions = _readList(
975 pluginPackageEl.element("liferay-versions"), "liferay-version");
976
977 List types = _readList(pluginPackageEl.element("types"), "type");
978
979 pluginPackage.setName(_readText(name));
980 pluginPackage.setRecommendedDeploymentContext(
981 _readText(
982 pluginPackageEl.elementText("recommended-deployment-context")));
983 pluginPackage.setModifiedDate(
984 _readDate(pluginPackageEl.elementText("modified-date")));
985 pluginPackage.setAuthor(
986 _readText(pluginPackageEl.elementText("author")));
987 pluginPackage.setTypes(types);
988 pluginPackage.setLicenses(
989 _readLicenseList(
990 pluginPackageEl.element("licenses"), "license"));
991 pluginPackage.setLiferayVersions(liferayVersions);
992 pluginPackage.setTags(
993 _readList(pluginPackageEl.element("tags"), "tag"));
994 pluginPackage.setShortDescription(
995 _readText(pluginPackageEl.elementText("short-description")));
996 pluginPackage.setLongDescription(
997 _readHtml(pluginPackageEl.elementText("long-description")));
998 pluginPackage.setChangeLog(
999 _readHtml(pluginPackageEl.elementText("change-log")));
1000 pluginPackage.setScreenshots(
1001 _readScreenshots(pluginPackageEl.element("screenshots")));
1002 pluginPackage.setPageURL(
1003 _readText(pluginPackageEl.elementText("page-url")));
1004 pluginPackage.setDownloadURL(
1005 _readText(pluginPackageEl.elementText("download-url")));
1006 pluginPackage.setDeploymentSettings(
1007 _readProperties(
1008 pluginPackageEl.element("deployment-settings"), "setting"));
1009
1010 return pluginPackage;
1011 }
1012
1013 private Properties _readProperties(Element parent, String childTagName) {
1014 Properties result = new Properties();
1015
1016 if (parent != null) {
1017 Iterator itr = parent.elements(childTagName).iterator();
1018
1019 while (itr.hasNext()) {
1020 Element tagEl = (Element)itr.next();
1021
1022 result.setProperty(
1023 tagEl.attribute("name").getValue(),
1024 tagEl.attribute("value").getValue());
1025 }
1026 }
1027
1028 return result;
1029 }
1030
1031 private List _readScreenshots(Element parent) {
1032 List result = new ArrayList();
1033
1034 if (parent != null) {
1035 List screenshots = parent.elements("screenshot");
1036
1037 Iterator itr = screenshots.iterator();
1038
1039 while (itr.hasNext()) {
1040 Element screenshotEl = (Element)itr.next();
1041
1042 Screenshot screenshot = new Screenshot();
1043
1044 screenshot.setThumbnailURL(
1045 screenshotEl.element("thumbnail-url").getText());
1046 screenshot.setLargeImageURL(
1047 screenshotEl.element("large-image-url").getText());
1048
1049 result.add(screenshot);
1050 }
1051 }
1052
1053 return result;
1054 }
1055
1056 private String _readText(String text) {
1057 return Html.stripHtml(GetterUtil.getString(text));
1058 }
1059
1060 private void _refreshUpdatesAvailableCache() {
1061 _updateAvailable = null;
1062 }
1063
1064 private void _reIndex() throws SystemException {
1065 if (LuceneUtil.INDEX_READ_ONLY) {
1066 return;
1067 }
1068
1069 IndexWriter writer = null;
1070
1071 try {
1072 PluginPackageIndexer.cleanIndex();
1073
1074 writer = LuceneUtil.getWriter(CompanyImpl.SYSTEM);
1075
1076 Iterator itr = _getAllAvailablePluginPackages().iterator();
1077
1078 while (itr.hasNext()) {
1079 PluginPackage pluginPackage = (PluginPackage)itr.next();
1080
1081 String[] statusAndInstalledVersion =
1082 _getStatusAndInstalledVersion(pluginPackage);
1083
1084 String status = statusAndInstalledVersion[0];
1085 String installedVersion = statusAndInstalledVersion[1];
1086
1087 org.apache.lucene.document.Document doc =
1088 PluginPackageIndexer.getAddPluginPackageDocument(
1089 pluginPackage.getModuleId(), pluginPackage.getName(),
1090 pluginPackage.getVersion(),
1091 pluginPackage.getModifiedDate(),
1092 pluginPackage.getAuthor(), pluginPackage.getTypes(),
1093 pluginPackage.getTags(), pluginPackage.getLicenses(),
1094 pluginPackage.getLiferayVersions(),
1095 pluginPackage.getShortDescription(),
1096 pluginPackage.getLongDescription(),
1097 pluginPackage.getChangeLog(),
1098 pluginPackage.getPageURL(),
1099 pluginPackage.getRepositoryURL(), status,
1100 installedVersion);
1101
1102 writer.addDocument(doc);
1103 }
1104 }
1105 catch (SystemException se) {
1106 throw se;
1107 }
1108 catch (Exception e) {
1109 throw new SystemException(e);
1110 }
1111 finally {
1112 try {
1113 if (writer != null) {
1114 LuceneUtil.write(CompanyImpl.SYSTEM);
1115 }
1116 }
1117 catch (Exception e) {
1118 _log.error(e);
1119 }
1120 }
1121 }
1122
1123 private RepositoryReport _reloadRepositories() throws SystemException {
1124 if (_log.isInfoEnabled()) {
1125 _log.info("Reloading repositories");
1126 }
1127
1128 RepositoryReport report = new RepositoryReport();
1129
1130 String[] repositoryURLs = _getRepositoryURLs();
1131
1132 for (int i = 0; i < repositoryURLs.length; i++) {
1133 String repositoryURL = repositoryURLs[i];
1134
1135 try {
1136 _loadRepository(repositoryURL);
1137
1138 report.addSuccess(repositoryURL);
1139 }
1140 catch(PluginPackageException pe) {
1141 report.addError(repositoryURL, pe);
1142
1143 _log.error(
1144 "Unable to load repository " + repositoryURL + " " +
1145 pe.toString());
1146 }
1147
1148 }
1149
1150 _reIndex();
1151
1152 return report;
1153 }
1154
1155 private void _registerInstalledPluginPackage(
1156 PluginPackage pluginPackage) {
1157
1158 _installedPluginPackages.addPluginPackage(pluginPackage);
1159
1160 _updateAvailable = null;
1161
1162 _indexPluginPackage(pluginPackage);
1163 }
1164
1165 private void _registerPluginPackageInstallation(
1166 String preliminaryContext) {
1167
1168 _installedPluginPackages.registerPluginPackageInstallation(
1169 preliminaryContext);
1170 }
1171
1172 private Hits _search(
1173 String keywords, String type, String tag, String license,
1174 String repositoryURL, String status)
1175 throws SystemException {
1176
1177 _checkRepositories(repositoryURL);
1178
1179 Searcher searcher = null;
1180
1181 try {
1182 HitsImpl hits = new HitsImpl();
1183
1184 BooleanQuery contextQuery = new BooleanQuery();
1185
1186 LuceneUtil.addRequiredTerm(
1187 contextQuery, LuceneFields.PORTLET_ID,
1188 PluginPackageIndexer.PORTLET_ID);
1189
1190 BooleanQuery fullQuery = new BooleanQuery();
1191
1192 fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
1193
1194 if (Validator.isNotNull(keywords)) {
1195 BooleanQuery searchQuery = new BooleanQuery();
1196
1197 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
1198 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
1199
1200 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1201 }
1202
1203 if (Validator.isNotNull(type)) {
1204 BooleanQuery searchQuery = new BooleanQuery();
1205
1206 LuceneUtil.addExactTerm(searchQuery, "type", type);
1207
1208 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1209 }
1210
1211 if (Validator.isNotNull(tag)) {
1212 BooleanQuery searchQuery = new BooleanQuery();
1213
1214 LuceneUtil.addExactTerm(searchQuery, "tag", tag);
1215
1216 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1217 }
1218
1219 if (Validator.isNotNull(repositoryURL)) {
1220 BooleanQuery searchQuery = new BooleanQuery();
1221
1222 Query query = new TermQuery(
1223 new Term("repositoryURL", repositoryURL));
1224
1225 searchQuery.add(query, BooleanClause.Occur.SHOULD);
1226
1227 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1228 }
1229
1230 if (Validator.isNotNull(license)) {
1231 BooleanQuery searchQuery = new BooleanQuery();
1232
1233 LuceneUtil.addExactTerm(searchQuery, "license", license);
1234
1235 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1236 }
1237
1238 if (Validator.isNotNull(status) && !status.equals("all")) {
1239 BooleanQuery searchQuery = new BooleanQuery();
1240
1241 if (status.equals(PluginPackageImpl.
1242 STATUS_NOT_INSTALLED_OR_OLDER_VERSION_INSTALLED)) {
1243
1244 LuceneUtil.addExactTerm(
1245 searchQuery, "status",
1246 PluginPackageImpl.STATUS_NOT_INSTALLED);
1247 LuceneUtil.addExactTerm(
1248 searchQuery, "status",
1249 PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED);
1250 }
1251 else {
1252 LuceneUtil.addExactTerm(searchQuery, "status", status);
1253 }
1254
1255 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1256 }
1257
1258 searcher = LuceneUtil.getSearcher(CompanyImpl.SYSTEM);
1259
1260 hits.recordHits(searcher.search(fullQuery), searcher);
1261
1262 return hits;
1263 }
1264 catch (Exception e) {
1265 return LuceneUtil.closeSearcher(searcher, keywords, e);
1266 }
1267 }
1268
1269 private void _unregisterInstalledPluginPackage(
1270 PluginPackage pluginPackage) {
1271
1272 _installedPluginPackages.removePluginPackage(pluginPackage);
1273 }
1274
1275 private void _updateInstallingPluginPackage(
1276 String preliminaryContext, PluginPackage pluginPackage) {
1277
1278 _installedPluginPackages.unregisterPluginPackageInstallation(
1279 preliminaryContext);
1280 _installedPluginPackages.registerPluginPackageInstallation(
1281 pluginPackage);
1282 }
1283
1284 private static Log _log = LogFactory.getLog(PluginPackageUtil.class);
1285
1286 private static PluginPackageUtil _instance = new PluginPackageUtil();
1287
1288 private LocalPluginPackageRepository _installedPluginPackages;
1289 private Map _repositoryCache;
1290 private Set _availableTagsCache;
1291 private Date _lastUpdateDate;
1292 private Boolean _updateAvailable;
1293 private boolean _settingUpdateAvailable;
1294
1295 private class UpdateAvailableRunner implements Runnable {
1296
1297 public void run() {
1298 try {
1299 setUpdateAvailable();
1300 }
1301 catch (Exception e) {
1302 _log.error(e, e);
1303 }
1304 }
1305
1306 protected void setUpdateAvailable() throws Exception {
1307 StopWatch stopWatch = null;
1308
1309 if (_log.isInfoEnabled()) {
1310 _log.info("Checking for available updates");
1311
1312 stopWatch = new StopWatch();
1313
1314 stopWatch.start();
1315 }
1316
1317 Iterator itr =
1318 _installedPluginPackages.getPluginPackages().iterator();
1319
1320 while (itr.hasNext()) {
1321 PluginPackage pluginPackage = (PluginPackage)itr.next();
1322
1323 PluginPackage availablePluginPackage = null;
1324
1325 if (_isIgnored(pluginPackage)) {
1326 continue;
1327 }
1328
1329 availablePluginPackage =
1330 PluginPackageUtil.getLatestAvailablePluginPackage(
1331 pluginPackage.getGroupId(),
1332 pluginPackage.getArtifactId());
1333
1334 if (availablePluginPackage == null) {
1335 continue;
1336 }
1337
1338 Version availablePluginPackageVersion = Version.getInstance(
1339 availablePluginPackage.getVersion());
1340
1341 if (availablePluginPackageVersion.isLaterVersionThan(
1342 pluginPackage.getVersion())) {
1343
1344 _updateAvailable = Boolean.TRUE;
1345
1346 break;
1347 }
1348 }
1349
1350 if (_updateAvailable == null) {
1351 _updateAvailable = Boolean.FALSE;
1352 }
1353
1354 _settingUpdateAvailable = false;
1355
1356 if (_log.isInfoEnabled()) {
1357 _log.info(
1358 "Finished checking for available updates in " +
1359 stopWatch.getTime() + " ms");
1360 }
1361 }
1362 }
1363
1364}