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.portal.plugin;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.plugin.License;
022    import com.liferay.portal.kernel.plugin.PluginPackage;
023    import com.liferay.portal.kernel.plugin.RemotePluginPackageRepository;
024    import com.liferay.portal.kernel.plugin.Screenshot;
025    import com.liferay.portal.kernel.plugin.Version;
026    import com.liferay.portal.kernel.search.Hits;
027    import com.liferay.portal.kernel.search.Indexer;
028    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
029    import com.liferay.portal.kernel.search.QueryConfig;
030    import com.liferay.portal.kernel.search.SearchContext;
031    import com.liferay.portal.kernel.util.ArrayUtil;
032    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlUtil;
035    import com.liferay.portal.kernel.util.Http;
036    import com.liferay.portal.kernel.util.HttpUtil;
037    import com.liferay.portal.kernel.util.ListUtil;
038    import com.liferay.portal.kernel.util.PropertiesUtil;
039    import com.liferay.portal.kernel.util.PropsKeys;
040    import com.liferay.portal.kernel.util.ReleaseInfo;
041    import com.liferay.portal.kernel.util.StringBundler;
042    import com.liferay.portal.kernel.util.StringPool;
043    import com.liferay.portal.kernel.util.StringUtil;
044    import com.liferay.portal.kernel.util.Time;
045    import com.liferay.portal.kernel.util.Validator;
046    import com.liferay.portal.kernel.xml.Attribute;
047    import com.liferay.portal.kernel.xml.Document;
048    import com.liferay.portal.kernel.xml.DocumentException;
049    import com.liferay.portal.kernel.xml.Element;
050    import com.liferay.portal.kernel.xml.SAXReaderUtil;
051    import com.liferay.portal.model.CompanyConstants;
052    import com.liferay.portal.model.Plugin;
053    import com.liferay.portal.security.lang.DoPrivilegedBean;
054    import com.liferay.portal.util.HttpImpl;
055    import com.liferay.portal.util.PrefsPropsUtil;
056    import com.liferay.portal.util.PropsValues;
057    
058    import java.io.IOException;
059    import java.io.InputStream;
060    import java.io.Serializable;
061    
062    import java.net.MalformedURLException;
063    
064    import java.text.DateFormat;
065    
066    import java.util.ArrayList;
067    import java.util.Arrays;
068    import java.util.Collection;
069    import java.util.Date;
070    import java.util.HashMap;
071    import java.util.List;
072    import java.util.Locale;
073    import java.util.Map;
074    import java.util.Properties;
075    import java.util.Set;
076    import java.util.TreeSet;
077    import java.util.jar.Attributes;
078    import java.util.jar.Manifest;
079    
080    import javax.servlet.ServletContext;
081    import javax.servlet.http.HttpServletResponse;
082    
083    import org.apache.commons.httpclient.HostConfiguration;
084    import org.apache.commons.httpclient.HttpClient;
085    import org.apache.commons.httpclient.methods.GetMethod;
086    import org.apache.commons.lang.time.StopWatch;
087    
088    /**
089     * @author Jorge Ferrer
090     * @author Brian Wing Shun Chan
091     * @author Sandeep Soni
092     */
093    public class PluginPackageUtil {
094    
095            public static final String REPOSITORY_XML_FILENAME_EXTENSION = "xml";
096    
097            public static final String REPOSITORY_XML_FILENAME_PREFIX =
098                    "liferay-plugin-repository";
099    
100            public static void endPluginPackageInstallation(String preliminaryContext) {
101                    _instance._endPluginPackageInstallation(preliminaryContext);
102            }
103    
104            public static List<PluginPackage> getAllAvailablePluginPackages()
105                    throws PortalException, SystemException {
106    
107                    return _instance._getAllAvailablePluginPackages();
108            }
109    
110            public static Collection<String> getAvailableTags() {
111                    return _instance._getAvailableTags();
112            }
113    
114            public static PluginPackage getInstalledPluginPackage(String context) {
115                    return _instance._getInstalledPluginPackage(context);
116            }
117    
118            public static List<PluginPackage> getInstalledPluginPackages() {
119                    return _instance._getInstalledPluginPackages();
120            }
121    
122            public static Date getLastUpdateDate() {
123                    return _instance._getLastUpdateDate();
124            }
125    
126            public static PluginPackage getLatestAvailablePluginPackage(
127                            String groupId, String artifactId)
128                    throws PortalException, SystemException {
129    
130                    return _instance._getLatestAvailablePluginPackage(groupId, artifactId);
131            }
132    
133            public static PluginPackage getLatestInstalledPluginPackage(
134                    String groupId, String artifactId) {
135    
136                    return _instance._getLatestInstalledPluginPackage(groupId, artifactId);
137            }
138    
139            public static PluginPackage getPluginPackageByModuleId(
140                            String moduleId, String repositoryURL)
141                    throws PortalException, SystemException {
142    
143                    return _instance._getPluginPackageByModuleId(moduleId, repositoryURL);
144            }
145    
146            public static PluginPackage getPluginPackageByURL(String url)
147                    throws PortalException, SystemException {
148    
149                    return _instance._getPluginPackageByURL(url);
150            }
151    
152            public static RemotePluginPackageRepository getRepository(
153                            String repositoryURL)
154                    throws PortalException, SystemException {
155    
156                    return _instance._getRepository(repositoryURL);
157            }
158    
159            public static String[] getRepositoryURLs() throws SystemException {
160                    return _instance._getRepositoryURLs();
161            }
162    
163            public static String[] getStatusAndInstalledVersion(
164                    PluginPackage pluginPackage) {
165    
166                    return _instance._getStatusAndInstalledVersion(pluginPackage);
167            }
168    
169            public static String[] getSupportedTypes() {
170                    return _instance._getSupportedTypes();
171            }
172    
173            public static boolean isCurrentVersionSupported(List<String> versions) {
174                    return _instance._isCurrentVersionSupported(versions);
175            }
176    
177            public static boolean isIgnored(PluginPackage pluginPackage)
178                    throws SystemException {
179    
180                    return _instance._isIgnored(pluginPackage);
181            }
182    
183            public static boolean isInstallationInProcess(String context) {
184                    return _instance._isInstallationInProcess(context);
185            }
186    
187            public static boolean isInstalled(String context) {
188                    return _instance._isInstalled(context);
189            }
190    
191            public static boolean isTrusted(String repositoryURL)
192                    throws SystemException {
193    
194                    return _instance._isTrusted(repositoryURL);
195            }
196    
197            public static boolean isUpdateAvailable() throws SystemException {
198                    return _instance._isUpdateAvailable();
199            }
200    
201            public static PluginPackage readPluginPackageProperties(
202                    String displayName, Properties properties) {
203    
204                    return _instance._readPluginPackageProperties(displayName, properties);
205            }
206    
207            public static PluginPackage readPluginPackageServletContext(
208                            ServletContext servletContext)
209                    throws DocumentException, IOException {
210    
211                    return _instance._readPluginPackageServletContext(servletContext);
212            }
213    
214            public static PluginPackage readPluginPackageXml(
215                    Element pluginPackageElement) {
216    
217                    return _instance._readPluginPackageXml(pluginPackageElement);
218            }
219    
220            public static PluginPackage readPluginPackageXml(String xml)
221                    throws DocumentException {
222    
223                    return _instance._readPluginPackageXml(xml);
224            }
225    
226            public static void refreshUpdatesAvailableCache() {
227                    _instance._refreshUpdatesAvailableCache();
228            }
229    
230            public static void registerInstalledPluginPackage(
231                            PluginPackage pluginPackage)
232                    throws PortalException {
233    
234                    _instance._registerInstalledPluginPackage(pluginPackage);
235            }
236    
237            public static void registerPluginPackageInstallation(
238                    String preliminaryContext) {
239    
240                    _instance._registerPluginPackageInstallation(preliminaryContext);
241            }
242    
243            public static RepositoryReport reloadRepositories()
244                    throws PortalException, SystemException {
245    
246                    return _instance._reloadRepositories();
247            }
248    
249            public static Hits search(
250                            String keywords, String type, String tag, String license,
251                            String repositoryURL, String status, int start, int end)
252                    throws PortalException, SystemException {
253    
254                    return _instance._search(
255                            keywords, type, tag, license, repositoryURL, status, start, end);
256            }
257    
258            public static void unregisterInstalledPluginPackage(
259                            PluginPackage pluginPackage)
260                    throws PortalException, SystemException {
261    
262                    _instance._unregisterInstalledPluginPackage(pluginPackage);
263            }
264    
265            public static void updateInstallingPluginPackage(
266                    String preliminaryContext, PluginPackage pluginPackage) {
267    
268                    _instance._updateInstallingPluginPackage(
269                            preliminaryContext, pluginPackage);
270            }
271    
272            private PluginPackageUtil() {
273                    _installedPluginPackages = new LocalPluginPackageRepository();
274                    _repositoryCache = new HashMap<String, RemotePluginPackageRepository>();
275                    _availableTagsCache = new TreeSet<String>();
276            }
277    
278            private void _checkRepositories(String repositoryURL)
279                    throws PortalException, SystemException {
280    
281                    String[] repositoryURLs = null;
282    
283                    if (Validator.isNotNull(repositoryURL)) {
284                            repositoryURLs = new String[] {repositoryURL};
285                    }
286                    else {
287                            repositoryURLs = _getRepositoryURLs();
288                    }
289    
290                    for (int i = 0; i < repositoryURLs.length; i++) {
291                            _getRepository(repositoryURLs[i]);
292                    }
293            }
294    
295            private void _endPluginPackageInstallation(String preliminaryContext) {
296                    _installedPluginPackages.unregisterPluginPackageInstallation(
297                            preliminaryContext);
298            }
299    
300            private PluginPackage _findLatestVersion(
301                    List<PluginPackage> pluginPackages) {
302    
303                    PluginPackage latestPluginPackage = null;
304    
305                    for (PluginPackage pluginPackage : pluginPackages) {
306                            if ((latestPluginPackage == null) ||
307                                    pluginPackage.isLaterVersionThan(latestPluginPackage)) {
308    
309                                    latestPluginPackage = pluginPackage;
310                            }
311                    }
312    
313                    return latestPluginPackage;
314            }
315    
316            private List<PluginPackage> _getAllAvailablePluginPackages()
317                    throws PortalException, SystemException {
318    
319                    List<PluginPackage> pluginPackages = new ArrayList<PluginPackage>();
320    
321                    String[] repositoryURLs = _getRepositoryURLs();
322    
323                    for (int i = 0; i < repositoryURLs.length; i++) {
324                            try {
325                                    RemotePluginPackageRepository repository = _getRepository(
326                                            repositoryURLs[i]);
327    
328                                    pluginPackages.addAll(repository.getPluginPackages());
329                            }
330                            catch (PluginPackageException ppe) {
331                                    String message = ppe.getMessage();
332    
333                                    if (message.startsWith("Unable to communicate")) {
334                                            if (_log.isWarnEnabled()) {
335                                                    _log.warn(message);
336                                            }
337                                    }
338                                    else {
339                                            _log.error(message);
340                                    }
341                            }
342                    }
343    
344                    return pluginPackages;
345            }
346    
347            private List<PluginPackage> _getAvailablePluginPackages(
348                            String groupId, String artifactId)
349                    throws PortalException, SystemException {
350    
351                    List<PluginPackage> pluginPackages = new ArrayList<PluginPackage>();
352    
353                    String[] repositoryURLs = _getRepositoryURLs();
354    
355                    for (int i = 0; i < repositoryURLs.length; i++) {
356                            RemotePluginPackageRepository repository = _getRepository(
357                                    repositoryURLs[i]);
358    
359                            List<PluginPackage> curPluginPackages =
360                                    repository.findPluginsByGroupIdAndArtifactId(
361                                            groupId, artifactId);
362    
363                            if (curPluginPackages != null) {
364                                    pluginPackages.addAll(curPluginPackages);
365                            }
366                    }
367    
368                    return pluginPackages;
369            }
370    
371            private Collection<String> _getAvailableTags() {
372                    return _availableTagsCache;
373            }
374    
375            private PluginPackage _getInstalledPluginPackage(String context) {
376                    return _installedPluginPackages.getPluginPackage(context);
377            }
378    
379            private List<PluginPackage> _getInstalledPluginPackages() {
380                    return _installedPluginPackages.getSortedPluginPackages();
381            }
382    
383            private Date _getLastUpdateDate() {
384                    return _lastUpdateDate;
385            }
386    
387            private PluginPackage _getLatestAvailablePluginPackage(
388                            String groupId, String artifactId)
389                    throws PortalException, SystemException {
390    
391                    List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
392                            groupId, artifactId);
393    
394                    return _findLatestVersion(pluginPackages);
395            }
396    
397            private PluginPackage _getLatestInstalledPluginPackage(
398                    String groupId, String artifactId) {
399    
400                    return _installedPluginPackages.getLatestPluginPackage(
401                            groupId, artifactId);
402            }
403    
404            private PluginPackage _getPluginPackageByModuleId(
405                            String moduleId, String repositoryURL)
406                    throws PortalException, SystemException {
407    
408                    RemotePluginPackageRepository repository = _getRepository(
409                            repositoryURL);
410    
411                    return repository.findPluginPackageByModuleId(moduleId);
412            }
413    
414            private PluginPackage _getPluginPackageByURL(String url)
415                    throws PortalException, SystemException {
416    
417                    String[] repositoryURLs = _getRepositoryURLs();
418    
419                    for (int i = 0; i < repositoryURLs.length; i++) {
420                            String repositoryURL = repositoryURLs[i];
421    
422                            try {
423                                    RemotePluginPackageRepository repository = _getRepository(
424                                            repositoryURL);
425    
426                                    return repository.findPluginByArtifactURL(url);
427                            }
428                            catch (PluginPackageException ppe) {
429                                    _log.error("Unable to load repository " + repositoryURL, ppe);
430                            }
431                    }
432    
433                    return null;
434            }
435    
436            private RemotePluginPackageRepository _getRepository(String repositoryURL)
437                    throws PortalException, SystemException {
438    
439                    RemotePluginPackageRepository repository = _repositoryCache.get(
440                            repositoryURL);
441    
442                    if (repository != null) {
443                            return repository;
444                    }
445    
446                    return _loadRepository(repositoryURL);
447            }
448    
449            private String[] _getRepositoryURLs() throws PluginPackageException {
450                    try {
451                            String[] trusted = PrefsPropsUtil.getStringArray(
452                                    PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
453                                    PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
454                            String[] untrusted = PrefsPropsUtil.getStringArray(
455                                    PropsKeys.PLUGIN_REPOSITORIES_UNTRUSTED, StringPool.NEW_LINE,
456                                    PropsValues.PLUGIN_REPOSITORIES_UNTRUSTED);
457    
458                            return ArrayUtil.append(trusted, untrusted);
459                    }
460                    catch (Exception e) {
461                            throw new PluginPackageException(
462                                    "Unable to read repository list", e);
463                    }
464            }
465    
466            private String[] _getStatusAndInstalledVersion(
467                    PluginPackage pluginPackage) {
468    
469                    PluginPackage installedPluginPackage =
470                            _installedPluginPackages.getLatestPluginPackage(
471                                    pluginPackage.getGroupId(), pluginPackage.getArtifactId());
472    
473                    String status = null;
474                    String installedVersion = null;
475    
476                    if (installedPluginPackage == null) {
477                            status = PluginPackageImpl.STATUS_NOT_INSTALLED;
478                    }
479                    else {
480                            installedVersion = installedPluginPackage.getVersion();
481    
482                            if (installedPluginPackage.isLaterVersionThan(pluginPackage)) {
483                                    status = PluginPackageImpl.STATUS_NEWER_VERSION_INSTALLED;
484                            }
485                            else if (installedPluginPackage.isPreviousVersionThan(
486                                                    pluginPackage)) {
487    
488                                    status = PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED;
489                            }
490                            else {
491                                    status = PluginPackageImpl.STATUS_SAME_VERSION_INSTALLED;
492                            }
493                    }
494    
495                    return new String[] {status, installedVersion};
496            }
497    
498            private String[] _getSupportedTypes() {
499                    return PropsValues.PLUGIN_TYPES;
500            }
501    
502            private void _indexPluginPackage(PluginPackage pluginPackage)
503                    throws PortalException {
504    
505                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
506    
507                    indexer.reindex(pluginPackage);
508            }
509    
510            private boolean _isCurrentVersionSupported(List<String> versions) {
511                    Version currentVersion = Version.getInstance(ReleaseInfo.getVersion());
512    
513                    for (String version : versions) {
514                            Version supportedVersion = Version.getInstance(version);
515    
516                            if (supportedVersion.includes(currentVersion)) {
517                                    return true;
518                            }
519                    }
520    
521                    return false;
522            }
523    
524            private boolean _isIgnored(PluginPackage pluginPackage)
525                    throws SystemException {
526    
527                    String packageId = pluginPackage.getPackageId();
528    
529                    String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
530                            PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
531                            StringPool.NEW_LINE,
532                            PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
533    
534                    for (int i = 0; i < pluginPackagesIgnored.length; i++) {
535                            String curPluginPackagesIgnored = pluginPackagesIgnored[i];
536    
537                            if (curPluginPackagesIgnored.endsWith(StringPool.STAR)) {
538                                    String prefix = curPluginPackagesIgnored.substring(
539                                            0, curPluginPackagesIgnored.length() - 2);
540    
541                                    if (packageId.startsWith(prefix)) {
542                                            return true;
543                                    }
544                            }
545                            else {
546                                    if (packageId.equals(curPluginPackagesIgnored)) {
547                                            return true;
548                                    }
549                            }
550                    }
551    
552                    return false;
553            }
554    
555            private boolean _isInstallationInProcess(String context) {
556                    if (_installedPluginPackages.getInstallingPluginPackage(
557                                    context) != null) {
558    
559                            return true;
560                    }
561                    else {
562                            return false;
563                    }
564            }
565    
566            private boolean _isInstalled(String context) {
567                    PluginPackage pluginPackage = _installedPluginPackages.getPluginPackage(
568                            context);
569    
570                    if (pluginPackage != null) {
571                            return true;
572                    }
573                    else {
574                            return false;
575                    }
576            }
577    
578            private boolean _isTrusted(String repositoryURL)
579                    throws PluginPackageException {
580    
581                    try {
582                            String[] trusted = PrefsPropsUtil.getStringArray(
583                                    PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
584                                    PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
585    
586                            if (ArrayUtil.contains(trusted, repositoryURL)) {
587                                    return true;
588                            }
589                            else {
590                                    return false;
591                            }
592                    }
593                    catch (Exception e) {
594                            throw new PluginPackageException(
595                                    "Unable to read repository list", e);
596                    }
597            }
598    
599            private boolean _isUpdateAvailable() throws SystemException {
600                    if (!PrefsPropsUtil.getBoolean(
601                                    PropsKeys.PLUGIN_NOTIFICATIONS_ENABLED,
602                                    PropsValues.PLUGIN_NOTIFICATIONS_ENABLED)) {
603    
604                            return false;
605                    }
606    
607                    if (_updateAvailable != null) {
608                            return _updateAvailable.booleanValue();
609                    }
610                    else if (!_settingUpdateAvailable) {
611                            _settingUpdateAvailable = true;
612    
613                            Thread indexerThread = new Thread(
614                                    new UpdateAvailableRunner(), PluginPackageUtil.class.getName());
615    
616                            indexerThread.setPriority(Thread.MIN_PRIORITY);
617    
618                            indexerThread.start();
619                    }
620    
621                    return false;
622            }
623    
624            private RemotePluginPackageRepository _loadRepository(String repositoryURL)
625                    throws PluginPackageException, PortalException {
626    
627                    RemotePluginPackageRepository repository = null;
628    
629                    StringBundler sb = new StringBundler(8);
630    
631                    if (!repositoryURL.startsWith(Http.HTTP_WITH_SLASH) &&
632                            !repositoryURL.startsWith(Http.HTTPS_WITH_SLASH)) {
633    
634                            sb.append(Http.HTTP_WITH_SLASH);
635                    }
636    
637                    sb.append(repositoryURL);
638                    sb.append(StringPool.SLASH);
639                    sb.append(REPOSITORY_XML_FILENAME_PREFIX);
640                    sb.append(StringPool.DASH);
641                    sb.append(ReleaseInfo.getVersion());
642                    sb.append(StringPool.PERIOD);
643                    sb.append(REPOSITORY_XML_FILENAME_EXTENSION);
644    
645                    String pluginsXmlURL = sb.toString();
646    
647                    try {
648                            HttpImpl httpImpl = null;
649    
650                            Object httpObject = HttpUtil.getHttp();
651    
652                            if (httpObject instanceof DoPrivilegedBean) {
653                                    DoPrivilegedBean doPrivilegedBean =
654                                            (DoPrivilegedBean)httpObject;
655    
656                                    httpImpl = (HttpImpl)doPrivilegedBean.getActualBean();
657                            }
658                            else {
659                                    httpImpl = (HttpImpl)httpObject;
660                            }
661    
662                            HostConfiguration hostConfiguration = httpImpl.getHostConfiguration(
663                                    pluginsXmlURL);
664    
665                            HttpClient httpClient = httpImpl.getClient(hostConfiguration);
666    
667                            httpImpl.proxifyState(httpClient.getState(), hostConfiguration);
668    
669                            GetMethod getFileMethod = new GetMethod(pluginsXmlURL);
670    
671                            byte[] bytes = null;
672    
673                            try {
674                                    int responseCode = httpClient.executeMethod(
675                                            hostConfiguration, getFileMethod);
676    
677                                    if (responseCode != HttpServletResponse.SC_OK) {
678                                            if (_log.isDebugEnabled()) {
679                                                    _log.debug(
680                                                            "A repository for version " +
681                                                                    ReleaseInfo.getVersion() + " was not found. " +
682                                                                            "Checking general repository");
683                                            }
684    
685                                            sb.setIndex(0);
686    
687                                            sb.append(repositoryURL);
688                                            sb.append(StringPool.SLASH);
689                                            sb.append(REPOSITORY_XML_FILENAME_PREFIX);
690                                            sb.append(StringPool.PERIOD);
691                                            sb.append(REPOSITORY_XML_FILENAME_EXTENSION);
692    
693                                            pluginsXmlURL = sb.toString();
694    
695                                            getFileMethod.releaseConnection();
696    
697                                            getFileMethod = new GetMethod(pluginsXmlURL);
698    
699                                            responseCode = httpClient.executeMethod(
700                                                    hostConfiguration, getFileMethod);
701    
702                                            if (responseCode != HttpServletResponse.SC_OK) {
703                                                    throw new PluginPackageException(
704                                                            "Unable to download file " + pluginsXmlURL +
705                                                                    " because of response code " + responseCode);
706                                            }
707                                    }
708    
709                                    bytes = getFileMethod.getResponseBody();
710                            }
711                            finally {
712                                    getFileMethod.releaseConnection();
713                            }
714    
715                            if ((bytes != null) && (bytes.length > 0)) {
716                                    repository = _parseRepositoryXml(
717                                            new String(bytes), repositoryURL);
718    
719                                    _repositoryCache.put(repositoryURL, repository);
720                                    _availableTagsCache.addAll(repository.getTags());
721                                    _lastUpdateDate = new Date();
722                                    _updateAvailable = null;
723    
724                                    return repository;
725                            }
726                            else {
727                                    _lastUpdateDate = new Date();
728    
729                                    throw new PluginPackageException("Download returned 0 bytes");
730                            }
731                    }
732                    catch (MalformedURLException murle) {
733                            _repositoryCache.remove(repositoryURL);
734    
735                            throw new PluginPackageException(
736                                    "Invalid URL " + pluginsXmlURL, murle);
737                    }
738                    catch (IOException ioe) {
739                            _repositoryCache.remove(repositoryURL);
740    
741                            throw new PluginPackageException(
742                                    "Unable to communicate with repository " + repositoryURL, ioe);
743                    }
744                    catch (DocumentException de) {
745                            _repositoryCache.remove(repositoryURL);
746    
747                            throw new PluginPackageException(
748                                    "Unable to parse plugin list for repository " + repositoryURL,
749                                    de);
750                    }
751            }
752    
753            private RemotePluginPackageRepository _parseRepositoryXml(
754                            String xml, String repositoryURL)
755                    throws DocumentException, PortalException {
756    
757                    List<String> supportedPluginTypes = Arrays.asList(getSupportedTypes());
758    
759                    if (_log.isDebugEnabled()) {
760                            _log.debug(
761                                    "Loading plugin repository " + repositoryURL + ":\n" + xml);
762                    }
763    
764                    RemotePluginPackageRepository pluginPackageRepository =
765                            new RemotePluginPackageRepository(repositoryURL);
766    
767                    if (xml == null) {
768                            return pluginPackageRepository;
769                    }
770    
771                    Document document = SAXReaderUtil.read(xml);
772    
773                    Element rootElement = document.getRootElement();
774    
775                    Properties settings = _readProperties(
776                            rootElement.element("settings"), "setting");
777    
778                    pluginPackageRepository.setSettings(settings);
779    
780                    List<Element> pluginPackageElements = rootElement.elements(
781                            "plugin-package");
782    
783                    for (Element pluginPackageElement : pluginPackageElements) {
784                            PluginPackage pluginPackage = _readPluginPackageXml(
785                                    pluginPackageElement);
786    
787                            if (!_isCurrentVersionSupported(
788                                            pluginPackage.getLiferayVersions())) {
789    
790                                    continue;
791                            }
792    
793                            boolean containsSupportedTypes = false;
794    
795                            List<String> pluginTypes = pluginPackage.getTypes();
796    
797                            for (String pluginType : pluginTypes) {
798                                    if (supportedPluginTypes.contains(pluginType)) {
799                                            containsSupportedTypes = true;
800    
801                                            break;
802                                    }
803                            }
804    
805                            if (!containsSupportedTypes) {
806                                    continue;
807                            }
808    
809                            pluginPackage.setRepository(pluginPackageRepository);
810    
811                            pluginPackageRepository.addPluginPackage(pluginPackage);
812    
813                            _indexPluginPackage(pluginPackage);
814                    }
815    
816                    return pluginPackageRepository;
817            }
818    
819            private Date _readDate(String text) {
820                    if (Validator.isNotNull(text)) {
821                            DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
822                                    Time.RFC822_FORMAT, Locale.US);
823    
824                            try {
825                                    return dateFormat.parse(text);
826                            }
827                            catch (Exception e) {
828                                    if (_log.isWarnEnabled()) {
829                                            _log.warn("Unable to parse date " + text);
830                                    }
831                            }
832                    }
833    
834                    return new Date();
835            }
836    
837            private String _readHtml(String text) {
838                    return GetterUtil.getString(text);
839            }
840    
841            private List<License> _readLicenseList(Element parentElement, String name) {
842                    List<License> licenses = new ArrayList<License>();
843    
844                    for (Element licenseElement : parentElement.elements(name)) {
845                            License license = new License();
846    
847                            license.setName(licenseElement.getText());
848    
849                            Attribute osiApproved = licenseElement.attribute("osi-approved");
850    
851                            if (osiApproved != null) {
852                                    license.setOsiApproved(
853                                            GetterUtil.getBoolean(osiApproved.getText()));
854                            }
855    
856                            Attribute url = licenseElement.attribute("url");
857    
858                            if (url != null) {
859                                    license.setUrl(url.getText());
860                            }
861    
862                            licenses.add(license);
863                    }
864    
865                    return licenses;
866            }
867    
868            private List<String> _readList(Element parentElement, String name) {
869                    List<String> list = new ArrayList<String>();
870    
871                    if (parentElement == null) {
872                            return list;
873                    }
874    
875                    for (Element element : parentElement.elements(name)) {
876                            String text = element.getText().trim().toLowerCase();
877    
878                            list.add(text);
879                    }
880    
881                    return list;
882            }
883    
884            private PluginPackage _readPluginPackageProperties(
885                    String displayName, Properties properties) {
886    
887                    int pos = displayName.indexOf("-portlet");
888    
889                    String pluginType = Plugin.TYPE_PORTLET;
890    
891                    if (pos == -1) {
892                            pos = displayName.indexOf("-ext");
893    
894                            pluginType = Plugin.TYPE_EXT;
895                    }
896    
897                    if (pos == -1) {
898                            pos = displayName.indexOf("-hook");
899    
900                            pluginType = Plugin.TYPE_HOOK;
901                    }
902    
903                    if (pos == -1) {
904                            pos = displayName.indexOf("-layouttpl");
905    
906                            pluginType = Plugin.TYPE_LAYOUT_TEMPLATE;
907                    }
908    
909                    if (pos == -1) {
910                            pos = displayName.indexOf("-theme");
911    
912                            pluginType = Plugin.TYPE_THEME;
913                    }
914    
915                    if (pos == -1) {
916                            pos = displayName.indexOf("-web");
917    
918                            pluginType = Plugin.TYPE_WEB;
919                    }
920    
921                    if (pos == -1) {
922                            return null;
923                    }
924    
925                    String displayPrefix = displayName.substring(0, pos);
926    
927                    String moduleGroupId = GetterUtil.getString(
928                            properties.getProperty("module-group-id"));
929                    String moduleArtifactId = displayPrefix + "-" + pluginType;
930    
931                    String moduleVersion = GetterUtil.getString(
932                            properties.getProperty("module-version"));
933    
934                    if (Validator.isNull(moduleVersion)) {
935                            int moduleVersionPos = pos + pluginType.length() + 2;
936    
937                            if (displayName.length() > moduleVersionPos) {
938                                    moduleVersion = displayName.substring(moduleVersionPos);
939                            }
940                            else {
941                                    moduleVersion = ReleaseInfo.getVersion();
942                            }
943                    }
944    
945                    String moduleId =
946                            moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
947                                    "/war";
948    
949                    String pluginName = GetterUtil.getString(
950                            properties.getProperty("name"));
951    
952                    String deploymentContext = GetterUtil.getString(
953                            properties.getProperty("recommended-deployment-context"),
954                            moduleArtifactId);
955    
956                    String author = GetterUtil.getString(properties.getProperty("author"));
957    
958                    List<String> types = new ArrayList<String>();
959    
960                    types.add(pluginType);
961    
962                    List<License> licenses = new ArrayList<License>();
963    
964                    String[] licensesArray = StringUtil.split(
965                            properties.getProperty("licenses"));
966    
967                    for (int i = 0; i < licensesArray.length; i++) {
968                            License license = new License();
969    
970                            license.setName(licensesArray[i].trim());
971                            license.setOsiApproved(true);
972    
973                            licenses.add(license);
974                    }
975    
976                    List<String> liferayVersions = new ArrayList<String>();
977    
978                    String[] liferayVersionsArray = StringUtil.split(
979                            properties.getProperty("liferay-versions"));
980    
981                    for (String liferayVersion : liferayVersionsArray) {
982                            liferayVersions.add(liferayVersion.trim());
983                    }
984    
985                    if (liferayVersions.size() == 0) {
986                            liferayVersions.add(ReleaseInfo.getVersion() + "+");
987                    }
988    
989                    List<String> tags = new ArrayList<String>();
990    
991                    String[] tagsArray = StringUtil.split(properties.getProperty("tags"));
992    
993                    for (String tag : tagsArray) {
994                            tags.add(tag.trim());
995                    }
996    
997                    String shortDescription = GetterUtil.getString(
998                            properties.getProperty("short-description"));
999                    String longDescription = GetterUtil.getString(
1000                            properties.getProperty("long-description"));
1001                    String changeLog = GetterUtil.getString(
1002                            properties.getProperty("change-log"));
1003                    String pageURL = GetterUtil.getString(
1004                            properties.getProperty("page-url"));
1005                    String downloadURL = GetterUtil.getString(
1006                            properties.getProperty("download-url"));
1007                    List<String> requiredDeploymentContexts = ListUtil.fromArray(
1008                            StringUtil.split(
1009                                    properties.getProperty("required-deployment-contexts")));
1010    
1011                    PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
1012    
1013                    pluginPackage.setName(pluginName);
1014                    pluginPackage.setRecommendedDeploymentContext(deploymentContext);
1015                    //pluginPackage.setModifiedDate(null);
1016                    pluginPackage.setAuthor(author);
1017                    pluginPackage.setTypes(types);
1018                    pluginPackage.setLicenses(licenses);
1019                    pluginPackage.setLiferayVersions(liferayVersions);
1020                    pluginPackage.setTags(tags);
1021                    pluginPackage.setShortDescription(shortDescription);
1022                    pluginPackage.setLongDescription(longDescription);
1023                    pluginPackage.setChangeLog(changeLog);
1024                    //pluginPackage.setScreenshots(null);
1025                    pluginPackage.setPageURL(pageURL);
1026                    pluginPackage.setDownloadURL(downloadURL);
1027                    //pluginPackage.setDeploymentSettings(null);
1028                    pluginPackage.setRequiredDeploymentContexts(requiredDeploymentContexts);
1029    
1030                    return pluginPackage;
1031            }
1032    
1033            /**
1034             * @see {@link
1035             *      com.liferay.portal.tools.deploy.BaseDeployer#readPluginPackage(
1036             *      java.io.File)}
1037             */
1038            private PluginPackage _readPluginPackageServletContext(
1039                            ServletContext servletContext)
1040                    throws DocumentException, IOException {
1041    
1042                    String servletContextName = servletContext.getServletContextName();
1043    
1044                    if (_log.isInfoEnabled()) {
1045                            if (servletContextName == null) {
1046                                    _log.info("Reading plugin package for the root context");
1047                            }
1048                            else {
1049                                    _log.info("Reading plugin package for " + servletContextName);
1050                            }
1051                    }
1052    
1053                    PluginPackage pluginPackage = null;
1054    
1055                    String xml = HttpUtil.URLtoString(
1056                            servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
1057    
1058                    if (xml != null) {
1059                            pluginPackage = _readPluginPackageXml(xml);
1060                    }
1061                    else {
1062                            String propertiesString = HttpUtil.URLtoString(
1063                                    servletContext.getResource(
1064                                            "/WEB-INF/liferay-plugin-package.properties"));
1065    
1066                            if (propertiesString != null) {
1067                                    if (_log.isDebugEnabled()) {
1068                                            _log.debug(
1069                                                    "Reading plugin package from " +
1070                                                            "liferay-plugin-package.properties");
1071                                    }
1072    
1073                                    Properties properties = PropertiesUtil.load(propertiesString);
1074    
1075                                    String displayName = servletContextName;
1076    
1077                                    if (displayName.startsWith(StringPool.SLASH)) {
1078                                            displayName = displayName.substring(1);
1079                                    }
1080    
1081                                    pluginPackage = _readPluginPackageProperties(
1082                                            displayName, properties);
1083                            }
1084    
1085                            if (pluginPackage == null) {
1086                                    if (_log.isDebugEnabled()) {
1087                                            _log.debug("Reading plugin package from MANIFEST.MF");
1088                                    }
1089    
1090                                    pluginPackage =_readPluginPackageServletManifest(
1091                                            servletContext);
1092                            }
1093                    }
1094    
1095                    pluginPackage.setContext(servletContextName);
1096    
1097                    return pluginPackage;
1098            }
1099    
1100            private PluginPackage _readPluginPackageServletManifest(
1101                            ServletContext servletContext)
1102                    throws IOException {
1103    
1104                    Attributes attributes = null;
1105    
1106                    String servletContextName = servletContext.getServletContextName();
1107    
1108                    InputStream inputStream = servletContext.getResourceAsStream(
1109                            "/META-INF/MANIFEST.MF");
1110    
1111                    if (inputStream != null) {
1112                            Manifest manifest = new Manifest(inputStream);
1113    
1114                            attributes = manifest.getMainAttributes();
1115                    }
1116                    else {
1117                            attributes = new Attributes();
1118                    }
1119    
1120                    String artifactGroupId = attributes.getValue(
1121                            "Implementation-Vendor-Id");
1122    
1123                    if (Validator.isNull(artifactGroupId)) {
1124                            artifactGroupId = attributes.getValue("Implementation-Vendor");
1125                    }
1126    
1127                    if (Validator.isNull(artifactGroupId)) {
1128                            artifactGroupId = GetterUtil.getString(
1129                                    attributes.getValue("Bundle-Vendor"), servletContextName);
1130                    }
1131    
1132                    String artifactId = attributes.getValue("Implementation-Title");
1133    
1134                    if (Validator.isNull(artifactId)) {
1135                            artifactId = GetterUtil.getString(
1136                                    attributes.getValue("Bundle-Name"), servletContextName);
1137                    }
1138    
1139                    String version = attributes.getValue("Implementation-Version");
1140    
1141                    if (Validator.isNull(version)) {
1142                            version = GetterUtil.getString(
1143                                    attributes.getValue("Bundle-Version"), Version.UNKNOWN);
1144                    }
1145    
1146                    if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
1147                            _log.warn(
1148                                    "Plugin package on context " + servletContextName +
1149                                            " cannot be tracked because this WAR does not contain a " +
1150                                                    "liferay-plugin-package.xml file");
1151                    }
1152    
1153                    PluginPackage pluginPackage = new PluginPackageImpl(
1154                            artifactGroupId + StringPool.SLASH + artifactId + StringPool.SLASH +
1155                                    version + StringPool.SLASH + "war");
1156    
1157                    pluginPackage.setName(artifactId);
1158    
1159                    String shortDescription = attributes.getValue("Bundle-Description");
1160    
1161                    if (Validator.isNotNull(shortDescription)) {
1162                            pluginPackage.setShortDescription(shortDescription);
1163                    }
1164    
1165                    String pageURL = attributes.getValue("Bundle-DocURL");
1166    
1167                    if (Validator.isNotNull(pageURL)) {
1168                            pluginPackage.setPageURL(pageURL);
1169                    }
1170    
1171                    return pluginPackage;
1172            }
1173    
1174            private PluginPackage _readPluginPackageXml(Element pluginPackageElement) {
1175                    String name = pluginPackageElement.elementText("name");
1176    
1177                    if (_log.isDebugEnabled()) {
1178                            _log.debug("Reading pluginPackage definition " + name);
1179                    }
1180    
1181                    PluginPackage pluginPackage = new PluginPackageImpl(
1182                            GetterUtil.getString(
1183                                    pluginPackageElement.elementText("module-id")));
1184    
1185                    List<String> liferayVersions = _readList(
1186                            pluginPackageElement.element("liferay-versions"),
1187                            "liferay-version");
1188    
1189                    List<String> types = _readList(
1190                            pluginPackageElement.element("types"), "type");
1191    
1192                    if (types.contains("layout-template")) {
1193                            types.remove("layout-template");
1194    
1195                            types.add(Plugin.TYPE_LAYOUT_TEMPLATE);
1196                    }
1197    
1198                    pluginPackage.setName(_readText(name));
1199                    pluginPackage.setRecommendedDeploymentContext(
1200                            _readText(
1201                                    pluginPackageElement.elementText(
1202                                            "recommended-deployment-context")));
1203                    pluginPackage.setModifiedDate(
1204                            _readDate(pluginPackageElement.elementText("modified-date")));
1205                    pluginPackage.setAuthor(
1206                            _readText(pluginPackageElement.elementText("author")));
1207                    pluginPackage.setTypes(types);
1208                    pluginPackage.setLicenses(
1209                            _readLicenseList(
1210                                    pluginPackageElement.element("licenses"), "license"));
1211                    pluginPackage.setLiferayVersions(liferayVersions);
1212                    pluginPackage.setTags(
1213                            _readList(pluginPackageElement.element("tags"), "tag"));
1214                    pluginPackage.setShortDescription(
1215                            _readText(pluginPackageElement.elementText("short-description")));
1216                    pluginPackage.setLongDescription(
1217                            _readHtml(pluginPackageElement.elementText("long-description")));
1218                    pluginPackage.setChangeLog(
1219                            _readHtml(pluginPackageElement.elementText("change-log")));
1220                    pluginPackage.setScreenshots(
1221                            _readScreenshots(pluginPackageElement.element("screenshots")));
1222                    pluginPackage.setPageURL(
1223                            _readText(pluginPackageElement.elementText("page-url")));
1224                    pluginPackage.setDownloadURL(
1225                            _readText(pluginPackageElement.elementText("download-url")));
1226                    pluginPackage.setDeploymentSettings(
1227                            _readProperties(
1228                                    pluginPackageElement.element("deployment-settings"),
1229                                    "setting"));
1230    
1231                    return pluginPackage;
1232            }
1233    
1234            private PluginPackage _readPluginPackageXml(String xml)
1235                    throws DocumentException {
1236    
1237                    Document document = SAXReaderUtil.read(xml);
1238    
1239                    Element rootElement = document.getRootElement();
1240    
1241                    return _readPluginPackageXml(rootElement);
1242            }
1243    
1244            private Properties _readProperties(Element parentElement, String name) {
1245                    Properties properties = new Properties();
1246    
1247                    if (parentElement == null) {
1248                            return properties;
1249                    }
1250    
1251                    for (Element element : parentElement.elements(name)) {
1252                            properties.setProperty(
1253                                    element.attributeValue("name"),
1254                                    element.attributeValue("value"));
1255                    }
1256    
1257                    return properties;
1258            }
1259    
1260            private List<Screenshot> _readScreenshots(Element parentElement) {
1261                    List<Screenshot> screenshots = new ArrayList<Screenshot>();
1262    
1263                    if (parentElement == null) {
1264                            return screenshots;
1265                    }
1266    
1267                    for (Element screenshotElement : parentElement.elements("screenshot")) {
1268                            Screenshot screenshot = new Screenshot();
1269    
1270                            screenshot.setThumbnailURL(
1271                                    screenshotElement.elementText("thumbnail-url"));
1272                            screenshot.setLargeImageURL(
1273                                    screenshotElement.elementText("large-image-url"));
1274    
1275                            screenshots.add(screenshot);
1276                    }
1277    
1278                    return screenshots;
1279            }
1280    
1281            private String _readText(String text) {
1282                    return HtmlUtil.extractText(GetterUtil.getString(text));
1283            }
1284    
1285            private void _refreshUpdatesAvailableCache() {
1286                    _updateAvailable = null;
1287            }
1288    
1289            private void _registerInstalledPluginPackage(PluginPackage pluginPackage)
1290                    throws PortalException {
1291    
1292                    _installedPluginPackages.addPluginPackage(pluginPackage);
1293    
1294                    _updateAvailable = null;
1295    
1296                    _indexPluginPackage(pluginPackage);
1297            }
1298    
1299            private void _registerPluginPackageInstallation(String preliminaryContext) {
1300                    _installedPluginPackages.registerPluginPackageInstallation(
1301                            preliminaryContext);
1302            }
1303    
1304            private RepositoryReport _reloadRepositories()
1305                    throws PortalException, SystemException {
1306    
1307                    if (_log.isInfoEnabled()) {
1308                            _log.info("Reloading repositories");
1309                    }
1310    
1311                    RepositoryReport repositoryReport = new RepositoryReport();
1312    
1313                    String[] repositoryURLs = _getRepositoryURLs();
1314    
1315                    for (int i = 0; i < repositoryURLs.length; i++) {
1316                            String repositoryURL = repositoryURLs[i];
1317    
1318                            try {
1319                                    _loadRepository(repositoryURL);
1320    
1321                                    repositoryReport.addSuccess(repositoryURL);
1322                            }
1323                            catch (PluginPackageException ppe) {
1324                                    repositoryReport.addError(repositoryURL, ppe);
1325    
1326                                    _log.error(
1327                                            "Unable to load repository " + repositoryURL + " " +
1328                                                    ppe.toString());
1329                            }
1330    
1331                    }
1332    
1333                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
1334    
1335                    indexer.reindex(new String[0]);
1336    
1337                    return repositoryReport;
1338            }
1339    
1340            private Hits _search(
1341                            String keywords, String type, String tag, String license,
1342                            String repositoryURL, String status, int start, int end)
1343                    throws PortalException, SystemException {
1344    
1345                    _checkRepositories(repositoryURL);
1346    
1347                    SearchContext searchContext = new SearchContext();
1348    
1349                    Map<String, Serializable> attributes =
1350                            new HashMap<String, Serializable>();
1351    
1352                    attributes.put("license", license);
1353                    attributes.put("repositoryURL", repositoryURL);
1354                    attributes.put("status", status);
1355                    attributes.put("tag", tag);
1356                    attributes.put("type", type);
1357    
1358                    searchContext.setAttributes(attributes);
1359    
1360                    searchContext.setCompanyId(CompanyConstants.SYSTEM);
1361                    searchContext.setEnd(end);
1362                    searchContext.setKeywords(keywords);
1363    
1364                    QueryConfig queryConfig = new QueryConfig();
1365    
1366                    queryConfig.setHighlightEnabled(false);
1367                    queryConfig.setScoreEnabled(false);
1368    
1369                    searchContext.setQueryConfig(queryConfig);
1370    
1371                    searchContext.setStart(start);
1372    
1373                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
1374    
1375                    return indexer.search(searchContext);
1376            }
1377    
1378            private void _unregisterInstalledPluginPackage(PluginPackage pluginPackage)
1379                    throws PortalException, SystemException {
1380    
1381                    _installedPluginPackages.removePluginPackage(pluginPackage);
1382    
1383                    try {
1384                            List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
1385                                    pluginPackage.getGroupId(), pluginPackage.getArtifactId());
1386    
1387                            for (PluginPackage availablePackage : pluginPackages) {
1388                                    _indexPluginPackage(availablePackage);
1389                            }
1390                    }
1391                    catch (PluginPackageException ppe) {
1392                            if (_log.isWarnEnabled()) {
1393                                    _log.warn(
1394                                            "Unable to reindex unistalled package " +
1395                                                    pluginPackage.getContext() + ": " + ppe.getMessage());
1396                            }
1397                    }
1398            }
1399    
1400            private void _updateInstallingPluginPackage(
1401                    String preliminaryContext, PluginPackage pluginPackage) {
1402    
1403                    _installedPluginPackages.unregisterPluginPackageInstallation(
1404                            preliminaryContext);
1405                    _installedPluginPackages.registerPluginPackageInstallation(
1406                            pluginPackage);
1407            }
1408    
1409            private static Log _log = LogFactoryUtil.getLog(PluginPackageUtil.class);
1410    
1411            private static PluginPackageUtil _instance = new PluginPackageUtil();
1412    
1413            private Set<String> _availableTagsCache;
1414            private LocalPluginPackageRepository _installedPluginPackages;
1415            private Date _lastUpdateDate;
1416            private Map<String, RemotePluginPackageRepository> _repositoryCache;
1417            private boolean _settingUpdateAvailable;
1418            private Boolean _updateAvailable;
1419    
1420            private class UpdateAvailableRunner implements Runnable {
1421    
1422                    @Override
1423                    public void run() {
1424                            try {
1425                                    setUpdateAvailable();
1426                            }
1427                            catch (Exception e) {
1428                                    if (_log.isWarnEnabled()) {
1429                                            _log.warn(e.getMessage());
1430                                    }
1431                            }
1432                    }
1433    
1434                    protected void setUpdateAvailable() throws Exception {
1435                            StopWatch stopWatch = null;
1436    
1437                            if (_log.isInfoEnabled()) {
1438                                    _log.info("Checking for available updates");
1439    
1440                                    stopWatch = new StopWatch();
1441    
1442                                    stopWatch.start();
1443                            }
1444    
1445                            for (PluginPackage pluginPackage :
1446                                            _installedPluginPackages.getPluginPackages()) {
1447    
1448                                    PluginPackage availablePluginPackage = null;
1449    
1450                                    if (_isIgnored(pluginPackage)) {
1451                                            continue;
1452                                    }
1453    
1454                                    availablePluginPackage =
1455                                            PluginPackageUtil.getLatestAvailablePluginPackage(
1456                                                    pluginPackage.getGroupId(),
1457                                                    pluginPackage.getArtifactId());
1458    
1459                                    if (availablePluginPackage == null) {
1460                                            continue;
1461                                    }
1462    
1463                                    Version availablePluginPackageVersion = Version.getInstance(
1464                                            availablePluginPackage.getVersion());
1465    
1466                                    if (availablePluginPackageVersion.isLaterVersionThan(
1467                                                    pluginPackage.getVersion())) {
1468    
1469                                            _updateAvailable = Boolean.TRUE;
1470    
1471                                            break;
1472                                    }
1473                            }
1474    
1475                            if (_updateAvailable == null) {
1476                                    _updateAvailable = Boolean.FALSE;
1477                            }
1478    
1479                            _settingUpdateAvailable = false;
1480    
1481                            if (_log.isInfoEnabled()) {
1482                                    _log.info(
1483                                            "Finished checking for available updates in " +
1484                                                    stopWatch.getTime() + " ms");
1485                            }
1486                    }
1487            }
1488    
1489    }