/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.plugin;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.CompanyConstants;
import com.liferay.portal.kernel.model.Plugin;
import com.liferay.portal.kernel.plugin.License;
import com.liferay.portal.kernel.plugin.PluginPackage;
import com.liferay.portal.kernel.plugin.RemotePluginPackageRepository;
import com.liferay.portal.kernel.plugin.Screenshot;
import com.liferay.portal.kernel.plugin.Version;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistryUtil;
import com.liferay.portal.kernel.search.QueryConfig;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.Http;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.ReleaseInfo;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Time;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Attribute;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.DocumentException;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.util.PrefsPropsUtil;
import com.liferay.portal.util.PropsValues;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.time.StopWatch;
/**
* @author Jorge Ferrer
* @author Brian Wing Shun Chan
* @author Sandeep Soni
*/
public class PluginPackageUtil {
public static void endPluginPackageInstallation(String preliminaryContext) {
_instance._endPluginPackageInstallation(preliminaryContext);
}
public static List<PluginPackage> getAllAvailablePluginPackages()
throws PortalException {
return _instance._getAllAvailablePluginPackages();
}
public static Collection<String> getAvailableTags() {
return _instance._getAvailableTags();
}
public static PluginPackage getInstalledPluginPackage(String context) {
return _instance._getInstalledPluginPackage(context);
}
public static List<PluginPackage> getInstalledPluginPackages() {
return _instance._getInstalledPluginPackages();
}
public static Date getLastUpdateDate() {
return _instance._getLastUpdateDate();
}
public static PluginPackage getLatestAvailablePluginPackage(
String groupId, String artifactId)
throws PortalException {
return _instance._getLatestAvailablePluginPackage(groupId, artifactId);
}
public static PluginPackage getLatestInstalledPluginPackage(
String groupId, String artifactId) {
return _instance._getLatestInstalledPluginPackage(groupId, artifactId);
}
public static PluginPackage getPluginPackageByModuleId(
String moduleId, String repositoryURL)
throws PortalException {
return _instance._getPluginPackageByModuleId(moduleId, repositoryURL);
}
public static PluginPackage getPluginPackageByURL(String url)
throws PortalException {
return _instance._getPluginPackageByURL(url);
}
public static RemotePluginPackageRepository getRepository(
String repositoryURL)
throws PortalException {
return _instance._getRepository(repositoryURL);
}
public static String[] getRepositoryURLs() {
return _instance._getRepositoryURLs();
}
public static String[] getStatusAndInstalledVersion(
PluginPackage pluginPackage) {
return _instance._getStatusAndInstalledVersion(pluginPackage);
}
public static String[] getSupportedTypes() {
return _instance._getSupportedTypes();
}
public static boolean isCurrentVersionSupported(List<String> versions) {
return _instance._isCurrentVersionSupported(versions);
}
public static boolean isIgnored(PluginPackage pluginPackage) {
return _instance._isIgnored(pluginPackage);
}
public static boolean isInstallationInProcess(String context) {
return _instance._isInstallationInProcess(context);
}
public static boolean isInstalled(String context) {
return _instance._isInstalled(context);
}
public static boolean isTrusted(String repositoryURL) {
return _instance._isTrusted(repositoryURL);
}
public static boolean isUpdateAvailable() {
return _instance._isUpdateAvailable();
}
public static PluginPackage readPluginPackageProperties(
String displayName, Properties properties) {
return _instance._readPluginPackageProperties(displayName, properties);
}
public static PluginPackage readPluginPackageServletContext(
ServletContext servletContext)
throws DocumentException, IOException {
return _instance._readPluginPackageServletContext(servletContext);
}
public static PluginPackage readPluginPackageXml(
Element pluginPackageElement) {
return _instance._readPluginPackageXml(pluginPackageElement);
}
public static PluginPackage readPluginPackageXml(String xml)
throws DocumentException {
return _instance._readPluginPackageXml(xml);
}
public static void refreshUpdatesAvailableCache() {
_instance._refreshUpdatesAvailableCache();
}
public static void registerInstalledPluginPackage(
PluginPackage pluginPackage)
throws PortalException {
_instance._registerInstalledPluginPackage(pluginPackage);
}
public static void registerPluginPackageInstallation(
String preliminaryContext) {
_instance._registerPluginPackageInstallation(preliminaryContext);
}
public static RepositoryReport reloadRepositories() throws PortalException {
return _instance._reloadRepositories();
}
public static Hits search(
String keywords, String type, String tag, String license,
String repositoryURL, String status, int start, int end)
throws PortalException {
return _instance._search(
keywords, type, tag, license, repositoryURL, status, start, end);
}
public static void unregisterInstalledPluginPackage(
PluginPackage pluginPackage)
throws PortalException {
_instance._unregisterInstalledPluginPackage(pluginPackage);
}
public static void updateInstallingPluginPackage(
String preliminaryContext, PluginPackage pluginPackage) {
_instance._updateInstallingPluginPackage(
preliminaryContext, pluginPackage);
}
private PluginPackageUtil() {
_installedPluginPackages = new LocalPluginPackageRepository();
_repositoryCache = new HashMap<>();
_availableTagsCache = new TreeSet<>();
}
private void _checkRepositories(String repositoryURL)
throws PortalException {
String[] repositoryURLs = null;
if (Validator.isNotNull(repositoryURL)) {
repositoryURLs = new String[] {repositoryURL};
}
else {
repositoryURLs = _getRepositoryURLs();
}
for (int i = 0; i < repositoryURLs.length; i++) {
_getRepository(repositoryURLs[i]);
}
}
private void _endPluginPackageInstallation(String preliminaryContext) {
_installedPluginPackages.unregisterPluginPackageInstallation(
preliminaryContext);
}
private PluginPackage _findLatestVersion(
List<PluginPackage> pluginPackages) {
PluginPackage latestPluginPackage = null;
for (PluginPackage pluginPackage : pluginPackages) {
if ((latestPluginPackage == null) ||
pluginPackage.isLaterVersionThan(latestPluginPackage)) {
latestPluginPackage = pluginPackage;
}
}
return latestPluginPackage;
}
private List<PluginPackage> _getAllAvailablePluginPackages()
throws PortalException {
List<PluginPackage> pluginPackages = new ArrayList<>();
String[] repositoryURLs = _getRepositoryURLs();
for (int i = 0; i < repositoryURLs.length; i++) {
try {
RemotePluginPackageRepository repository = _getRepository(
repositoryURLs[i]);
pluginPackages.addAll(repository.getPluginPackages());
}
catch (PluginPackageException ppe) {
String message = ppe.getMessage();
if (message.startsWith("Unable to communicate")) {
if (_log.isWarnEnabled()) {
_log.warn(message);
}
}
else {
_log.error(message);
}
}
}
return pluginPackages;
}
private List<PluginPackage> _getAvailablePluginPackages(
String groupId, String artifactId)
throws PortalException {
List<PluginPackage> pluginPackages = new ArrayList<>();
String[] repositoryURLs = _getRepositoryURLs();
for (int i = 0; i < repositoryURLs.length; i++) {
RemotePluginPackageRepository repository = _getRepository(
repositoryURLs[i]);
List<PluginPackage> curPluginPackages =
repository.findPluginsByGroupIdAndArtifactId(
groupId, artifactId);
if (curPluginPackages != null) {
pluginPackages.addAll(curPluginPackages);
}
}
return pluginPackages;
}
private Collection<String> _getAvailableTags() {
return _availableTagsCache;
}
private PluginPackage _getInstalledPluginPackage(String context) {
return _installedPluginPackages.getPluginPackage(context);
}
private List<PluginPackage> _getInstalledPluginPackages() {
return _installedPluginPackages.getSortedPluginPackages();
}
private Date _getLastUpdateDate() {
return _lastUpdateDate;
}
private PluginPackage _getLatestAvailablePluginPackage(
String groupId, String artifactId)
throws PortalException {
List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
groupId, artifactId);
return _findLatestVersion(pluginPackages);
}
private PluginPackage _getLatestInstalledPluginPackage(
String groupId, String artifactId) {
return _installedPluginPackages.getLatestPluginPackage(
groupId, artifactId);
}
private PluginPackage _getPluginPackageByModuleId(
String moduleId, String repositoryURL)
throws PortalException {
RemotePluginPackageRepository repository = _getRepository(
repositoryURL);
return repository.findPluginPackageByModuleId(moduleId);
}
private PluginPackage _getPluginPackageByURL(String url)
throws PortalException {
String[] repositoryURLs = _getRepositoryURLs();
for (int i = 0; i < repositoryURLs.length; i++) {
String repositoryURL = repositoryURLs[i];
try {
RemotePluginPackageRepository repository = _getRepository(
repositoryURL);
return repository.findPluginByArtifactURL(url);
}
catch (PluginPackageException ppe) {
_log.error("Unable to load repository " + repositoryURL, ppe);
}
}
return null;
}
private RemotePluginPackageRepository _getRepository(String repositoryURL)
throws PortalException {
RemotePluginPackageRepository repository = _repositoryCache.get(
repositoryURL);
if (repository != null) {
return repository;
}
return _loadRepository(repositoryURL);
}
private String[] _getRepositoryURLs() throws PluginPackageException {
try {
String[] trusted = PrefsPropsUtil.getStringArray(
PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
String[] untrusted = PrefsPropsUtil.getStringArray(
PropsKeys.PLUGIN_REPOSITORIES_UNTRUSTED, StringPool.NEW_LINE,
PropsValues.PLUGIN_REPOSITORIES_UNTRUSTED);
return ArrayUtil.append(trusted, untrusted);
}
catch (Exception e) {
throw new PluginPackageException(
"Unable to read repository list", e);
}
}
private String[] _getStatusAndInstalledVersion(
PluginPackage pluginPackage) {
PluginPackage installedPluginPackage =
_installedPluginPackages.getLatestPluginPackage(
pluginPackage.getGroupId(), pluginPackage.getArtifactId());
String status = null;
String installedVersion = null;
if (installedPluginPackage == null) {
status = PluginPackageImpl.STATUS_NOT_INSTALLED;
}
else {
installedVersion = installedPluginPackage.getVersion();
if (installedPluginPackage.isLaterVersionThan(pluginPackage)) {
status = PluginPackageImpl.STATUS_NEWER_VERSION_INSTALLED;
}
else if (installedPluginPackage.isPreviousVersionThan(
pluginPackage)) {
status = PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED;
}
else {
status = PluginPackageImpl.STATUS_SAME_VERSION_INSTALLED;
}
}
return new String[] {status, installedVersion};
}
private String[] _getSupportedTypes() {
return PropsValues.PLUGIN_TYPES;
}
private void _indexPluginPackage(PluginPackage pluginPackage)
throws PortalException {
Indexer<PluginPackage> indexer = IndexerRegistryUtil.getIndexer(
PluginPackage.class);
indexer.reindex(pluginPackage);
}
private boolean _isCurrentVersionSupported(List<String> versions) {
Version currentVersion = Version.getInstance(ReleaseInfo.getVersion());
for (String version : versions) {
Version supportedVersion = Version.getInstance(version);
if (supportedVersion.includes(currentVersion)) {
return true;
}
}
return false;
}
private boolean _isIgnored(PluginPackage pluginPackage) {
String packageId = pluginPackage.getPackageId();
String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
StringPool.NEW_LINE,
PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
for (int i = 0; i < pluginPackagesIgnored.length; i++) {
String curPluginPackagesIgnored = pluginPackagesIgnored[i];
if (curPluginPackagesIgnored.endsWith(StringPool.STAR)) {
String prefix = curPluginPackagesIgnored.substring(
0, curPluginPackagesIgnored.length() - 2);
if (packageId.startsWith(prefix)) {
return true;
}
}
else {
if (packageId.equals(curPluginPackagesIgnored)) {
return true;
}
}
}
return false;
}
private boolean _isInstallationInProcess(String context) {
if (_installedPluginPackages.getInstallingPluginPackage(context) !=
null) {
return true;
}
else {
return false;
}
}
private boolean _isInstalled(String context) {
PluginPackage pluginPackage = _installedPluginPackages.getPluginPackage(
context);
if (pluginPackage != null) {
return true;
}
else {
return false;
}
}
private boolean _isTrusted(String repositoryURL)
throws PluginPackageException {
try {
String[] trusted = PrefsPropsUtil.getStringArray(
PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
if (ArrayUtil.contains(trusted, repositoryURL)) {
return true;
}
else {
return false;
}
}
catch (Exception e) {
throw new PluginPackageException(
"Unable to read repository list", e);
}
}
private boolean _isUpdateAvailable() {
if (!PrefsPropsUtil.getBoolean(
PropsKeys.PLUGIN_NOTIFICATIONS_ENABLED,
PropsValues.PLUGIN_NOTIFICATIONS_ENABLED)) {
return false;
}
if (_updateAvailable != null) {
return _updateAvailable.booleanValue();
}
else if (!_settingUpdateAvailable) {
_settingUpdateAvailable = true;
Thread indexerThread = new Thread(
new UpdateAvailableRunner(), PluginPackageUtil.class.getName());
indexerThread.setPriority(Thread.MIN_PRIORITY);
indexerThread.start();
}
return false;
}
private RemotePluginPackageRepository _loadRepository(String repositoryURL)
throws PluginPackageException, PortalException {
RemotePluginPackageRepository repository = null;
StringBundler sb = new StringBundler(8);
if (!repositoryURL.startsWith(Http.HTTP_WITH_SLASH) &&
!repositoryURL.startsWith(Http.HTTPS_WITH_SLASH)) {
sb.append(Http.HTTP_WITH_SLASH);
}
sb.append(repositoryURL);
sb.append(StringPool.SLASH);
sb.append(PluginPackage.REPOSITORY_XML_FILENAME_PREFIX);
sb.append(StringPool.DASH);
sb.append(ReleaseInfo.getVersion());
sb.append(StringPool.PERIOD);
sb.append(PluginPackage.REPOSITORY_XML_FILENAME_EXTENSION);
String pluginsXmlURL = sb.toString();
try {
Http.Options options = new Http.Options();
options.setLocation(pluginsXmlURL);
options.setPost(false);
byte[] bytes = HttpUtil.URLtoByteArray(options);
Http.Response response = options.getResponse();
int responseCode = response.getResponseCode();
if (responseCode != HttpServletResponse.SC_OK) {
if (_log.isDebugEnabled()) {
_log.debug(
"A repository for version " + ReleaseInfo.getVersion() +
" was not found. Checking general repository");
}
sb.setIndex(0);
sb.append(repositoryURL);
sb.append(StringPool.SLASH);
sb.append(PluginPackage.REPOSITORY_XML_FILENAME_PREFIX);
sb.append(StringPool.PERIOD);
sb.append(PluginPackage.REPOSITORY_XML_FILENAME_EXTENSION);
pluginsXmlURL = sb.toString();
options = new Http.Options();
options.setLocation(pluginsXmlURL);
options.setPost(false);
bytes = HttpUtil.URLtoByteArray(options);
response = options.getResponse();
if (responseCode != HttpServletResponse.SC_OK) {
throw new PluginPackageException(
"Unable to download file " + pluginsXmlURL +
" because of response code " + responseCode);
}
}
if (ArrayUtil.isNotEmpty(bytes)) {
repository = _parseRepositoryXml(
new String(bytes), repositoryURL);
_repositoryCache.put(repositoryURL, repository);
_availableTagsCache.addAll(repository.getTags());
_lastUpdateDate = new Date();
_updateAvailable = null;
return repository;
}
_lastUpdateDate = new Date();
throw new PluginPackageException("Download returned 0 bytes");
}
catch (MalformedURLException murle) {
_repositoryCache.remove(repositoryURL);
throw new PluginPackageException(
"Invalid URL " + pluginsXmlURL, murle);
}
catch (IOException ioe) {
_repositoryCache.remove(repositoryURL);
throw new PluginPackageException(
"Unable to communicate with repository " + repositoryURL, ioe);
}
catch (DocumentException de) {
_repositoryCache.remove(repositoryURL);
throw new PluginPackageException(
"Unable to parse plugin list for repository " + repositoryURL,
de);
}
}
private RemotePluginPackageRepository _parseRepositoryXml(
String xml, String repositoryURL)
throws DocumentException, PortalException {
List<String> supportedPluginTypes = Arrays.asList(getSupportedTypes());
if (_log.isDebugEnabled()) {
_log.debug(
"Loading plugin repository " + repositoryURL + ":\n" + xml);
}
RemotePluginPackageRepository pluginPackageRepository =
new RemotePluginPackageRepository(repositoryURL);
if (xml == null) {
return pluginPackageRepository;
}
Document document = SAXReaderUtil.read(xml);
Element rootElement = document.getRootElement();
Properties settings = _readProperties(
rootElement.element("settings"), "setting");
pluginPackageRepository.setSettings(settings);
List<Element> pluginPackageElements = rootElement.elements(
"plugin-package");
for (Element pluginPackageElement : pluginPackageElements) {
PluginPackage pluginPackage = _readPluginPackageXml(
pluginPackageElement);
if (!_isCurrentVersionSupported(
pluginPackage.getLiferayVersions())) {
continue;
}
boolean containsSupportedTypes = false;
List<String> pluginTypes = pluginPackage.getTypes();
for (String pluginType : pluginTypes) {
if (supportedPluginTypes.contains(pluginType)) {
containsSupportedTypes = true;
break;
}
}
if (!containsSupportedTypes) {
continue;
}
pluginPackage.setRepository(pluginPackageRepository);
pluginPackageRepository.addPluginPackage(pluginPackage);
_indexPluginPackage(pluginPackage);
}
return pluginPackageRepository;
}
private Date _readDate(String text) {
if (Validator.isNotNull(text)) {
DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
Time.RFC822_FORMAT, LocaleUtil.US);
try {
return dateFormat.parse(text);
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn("Unable to parse date " + text);
}
}
}
return new Date();
}
private String _readHtml(String text) {
return GetterUtil.getString(text);
}
private List<License> _readLicenseList(Element parentElement, String name) {
List<License> licenses = new ArrayList<>();
for (Element licenseElement : parentElement.elements(name)) {
License license = new License();
license.setName(licenseElement.getText());
Attribute osiApproved = licenseElement.attribute("osi-approved");
if (osiApproved != null) {
license.setOsiApproved(
GetterUtil.getBoolean(osiApproved.getText()));
}
Attribute url = licenseElement.attribute("url");
if (url != null) {
license.setUrl(url.getText());
}
licenses.add(license);
}
return licenses;
}
private List<String> _readList(Element parentElement, String name) {
List<String> list = new ArrayList<>();
if (parentElement == null) {
return list;
}
for (Element element : parentElement.elements(name)) {
String text = StringUtil.toLowerCase(element.getText().trim());
list.add(text);
}
return list;
}
private PluginPackage _readPluginPackageProperties(
String displayName, Properties properties) {
int pos = displayName.indexOf("-portlet");
String pluginType = Plugin.TYPE_PORTLET;
if (pos == -1) {
pos = displayName.indexOf("-ext");
pluginType = Plugin.TYPE_EXT;
}
if (pos == -1) {
pos = displayName.indexOf("-hook");
pluginType = Plugin.TYPE_HOOK;
}
if (pos == -1) {
pos = displayName.indexOf("-layouttpl");
pluginType = Plugin.TYPE_LAYOUT_TEMPLATE;
}
if (pos == -1) {
pos = displayName.indexOf("-theme");
pluginType = Plugin.TYPE_THEME;
}
if (pos == -1) {
pos = displayName.indexOf("-web");
pluginType = Plugin.TYPE_WEB;
}
if (pos == -1) {
return null;
}
String displayPrefix = displayName.substring(0, pos);
String moduleGroupId = GetterUtil.getString(
properties.getProperty("module-group-id"));
String moduleArtifactId = displayPrefix + "-" + pluginType;
String moduleVersion = GetterUtil.getString(
properties.getProperty("module-version"));
if (Validator.isNull(moduleVersion)) {
int moduleVersionPos = pos + pluginType.length() + 2;
if (displayName.length() > moduleVersionPos) {
moduleVersion = displayName.substring(moduleVersionPos);
}
else {
moduleVersion = ReleaseInfo.getVersion();
}
}
String moduleId =
moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
"/war";
String pluginName = GetterUtil.getString(
properties.getProperty("name"));
String deploymentContext = GetterUtil.getString(
properties.getProperty("recommended-deployment-context"),
moduleArtifactId);
String author = GetterUtil.getString(properties.getProperty("author"));
List<String> types = new ArrayList<>();
types.add(pluginType);
List<License> licenses = new ArrayList<>();
String[] licensesArray = StringUtil.split(
properties.getProperty("licenses"));
for (int i = 0; i < licensesArray.length; i++) {
License license = new License();
license.setName(licensesArray[i].trim());
license.setOsiApproved(true);
licenses.add(license);
}
List<String> liferayVersions = new ArrayList<>();
String[] liferayVersionsArray = StringUtil.split(
properties.getProperty("liferay-versions"));
for (String liferayVersion : liferayVersionsArray) {
liferayVersions.add(liferayVersion.trim());
}
if (liferayVersions.isEmpty()) {
liferayVersions.add(ReleaseInfo.getVersion() + "+");
}
List<String> tags = new ArrayList<>();
String[] tagsArray = StringUtil.split(properties.getProperty("tags"));
for (String tag : tagsArray) {
tags.add(tag.trim());
}
String shortDescription = GetterUtil.getString(
properties.getProperty("short-description"));
String longDescription = GetterUtil.getString(
properties.getProperty("long-description"));
String changeLog = GetterUtil.getString(
properties.getProperty("change-log"));
String pageURL = GetterUtil.getString(
properties.getProperty("page-url"));
String downloadURL = GetterUtil.getString(
properties.getProperty("download-url"));
List<String> requiredDeploymentContexts = ListUtil.fromArray(
StringUtil.split(
properties.getProperty("required-deployment-contexts")));
PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
pluginPackage.setName(pluginName);
pluginPackage.setRecommendedDeploymentContext(deploymentContext);
//pluginPackage.setModifiedDate(null);
pluginPackage.setAuthor(author);
pluginPackage.setTypes(types);
pluginPackage.setLicenses(licenses);
pluginPackage.setLiferayVersions(liferayVersions);
pluginPackage.setTags(tags);
pluginPackage.setShortDescription(shortDescription);
pluginPackage.setLongDescription(longDescription);
pluginPackage.setChangeLog(changeLog);
//pluginPackage.setScreenshots(null);
pluginPackage.setPageURL(pageURL);
pluginPackage.setDownloadURL(downloadURL);
//pluginPackage.setDeploymentSettings(null);
pluginPackage.setRequiredDeploymentContexts(requiredDeploymentContexts);
return pluginPackage;
}
/**
* @see com.liferay.portal.tools.deploy.BaseDeployer#readPluginPackage(
* java.io.File)
*/
private PluginPackage _readPluginPackageServletContext(
ServletContext servletContext)
throws DocumentException, IOException {
String servletContextName = servletContext.getServletContextName();
if (_log.isInfoEnabled()) {
if (servletContextName == null) {
_log.info("Reading plugin package for the root context");
}
else {
_log.info("Reading plugin package for " + servletContextName);
}
}
PluginPackage pluginPackage = null;
String xml = HttpUtil.URLtoString(
servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
if (xml != null) {
pluginPackage = _readPluginPackageXml(xml);
}
else {
String propertiesString = HttpUtil.URLtoString(
servletContext.getResource(
"/WEB-INF/liferay-plugin-package.properties"));
if (propertiesString != null) {
if (_log.isDebugEnabled()) {
_log.debug(
"Reading plugin package from " +
"liferay-plugin-package.properties");
}
Properties properties = PropertiesUtil.load(propertiesString);
String displayName = servletContextName;
if (displayName.startsWith(StringPool.SLASH)) {
displayName = displayName.substring(1);
}
pluginPackage = _readPluginPackageProperties(
displayName, properties);
}
if (pluginPackage == null) {
if (_log.isDebugEnabled()) {
_log.debug("Reading plugin package from MANIFEST.MF");
}
pluginPackage = _readPluginPackageServletManifest(
servletContext);
}
}
pluginPackage.setContext(servletContextName);
return pluginPackage;
}
private PluginPackage _readPluginPackageServletManifest(
ServletContext servletContext)
throws IOException {
Attributes attributes = null;
String servletContextName = servletContext.getServletContextName();
InputStream inputStream = servletContext.getResourceAsStream(
"/META-INF/MANIFEST.MF");
if (inputStream != null) {
Manifest manifest = new Manifest(inputStream);
attributes = manifest.getMainAttributes();
}
else {
attributes = new Attributes();
}
String artifactGroupId = attributes.getValue(
"Implementation-Vendor-Id");
if (Validator.isNull(artifactGroupId)) {
artifactGroupId = attributes.getValue("Implementation-Vendor");
}
if (Validator.isNull(artifactGroupId)) {
artifactGroupId = GetterUtil.getString(
attributes.getValue("Bundle-Vendor"), servletContextName);
}
String artifactId = attributes.getValue("Implementation-Title");
if (Validator.isNull(artifactId)) {
artifactId = GetterUtil.getString(
attributes.getValue("Bundle-Name"), servletContextName);
}
String version = attributes.getValue("Implementation-Version");
if (Validator.isNull(version)) {
version = GetterUtil.getString(
attributes.getValue("Bundle-Version"), Version.UNKNOWN);
}
if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
_log.warn(
"Plugin package on context " + servletContextName +
" cannot be tracked because this WAR does not contain a " +
"liferay-plugin-package.xml file");
}
PluginPackage pluginPackage = new PluginPackageImpl(
artifactGroupId + StringPool.SLASH + artifactId + StringPool.SLASH +
version + StringPool.SLASH + "war");
pluginPackage.setName(artifactId);
String shortDescription = attributes.getValue("Bundle-Description");
if (Validator.isNotNull(shortDescription)) {
pluginPackage.setShortDescription(shortDescription);
}
String pageURL = attributes.getValue("Bundle-DocURL");
if (Validator.isNotNull(pageURL)) {
pluginPackage.setPageURL(pageURL);
}
return pluginPackage;
}
private PluginPackage _readPluginPackageXml(Element pluginPackageElement) {
String name = pluginPackageElement.elementText("name");
if (_log.isDebugEnabled()) {
_log.debug("Reading pluginPackage definition " + name);
}
PluginPackage pluginPackage = new PluginPackageImpl(
GetterUtil.getString(
pluginPackageElement.elementText("module-id")));
List<String> liferayVersions = _readList(
pluginPackageElement.element("liferay-versions"),
"liferay-version");
List<String> types = _readList(
pluginPackageElement.element("types"), "type");
if (types.contains("layout-template")) {
types.remove("layout-template");
types.add(Plugin.TYPE_LAYOUT_TEMPLATE);
}
pluginPackage.setName(_readText(name));
pluginPackage.setRecommendedDeploymentContext(
_readText(
pluginPackageElement.elementText(
"recommended-deployment-context")));
pluginPackage.setRequiredDeploymentContexts(
_readList(
pluginPackageElement.element("required-deployment-contexts"),
"required-deployment-context"));
pluginPackage.setModifiedDate(
_readDate(pluginPackageElement.elementText("modified-date")));
pluginPackage.setAuthor(
_readText(pluginPackageElement.elementText("author")));
pluginPackage.setTypes(types);
pluginPackage.setLicenses(
_readLicenseList(
pluginPackageElement.element("licenses"), "license"));
pluginPackage.setLiferayVersions(liferayVersions);
pluginPackage.setTags(
_readList(pluginPackageElement.element("tags"), "tag"));
pluginPackage.setShortDescription(
_readText(pluginPackageElement.elementText("short-description")));
pluginPackage.setLongDescription(
_readHtml(pluginPackageElement.elementText("long-description")));
pluginPackage.setChangeLog(
_readHtml(pluginPackageElement.elementText("change-log")));
pluginPackage.setScreenshots(
_readScreenshots(pluginPackageElement.element("screenshots")));
pluginPackage.setPageURL(
_readText(pluginPackageElement.elementText("page-url")));
pluginPackage.setDownloadURL(
_readText(pluginPackageElement.elementText("download-url")));
pluginPackage.setDeploymentSettings(
_readProperties(
pluginPackageElement.element("deployment-settings"),
"setting"));
return pluginPackage;
}
private PluginPackage _readPluginPackageXml(String xml)
throws DocumentException {
Document document = SAXReaderUtil.read(xml);
Element rootElement = document.getRootElement();
return _readPluginPackageXml(rootElement);
}
private Properties _readProperties(Element parentElement, String name) {
Properties properties = new Properties();
if (parentElement == null) {
return properties;
}
for (Element element : parentElement.elements(name)) {
properties.setProperty(
element.attributeValue("name"),
element.attributeValue("value"));
}
return properties;
}
private List<Screenshot> _readScreenshots(Element parentElement) {
List<Screenshot> screenshots = new ArrayList<>();
if (parentElement == null) {
return screenshots;
}
for (Element screenshotElement : parentElement.elements("screenshot")) {
Screenshot screenshot = new Screenshot();
screenshot.setThumbnailURL(
screenshotElement.elementText("thumbnail-url"));
screenshot.setLargeImageURL(
screenshotElement.elementText("large-image-url"));
screenshots.add(screenshot);
}
return screenshots;
}
private String _readText(String text) {
return HtmlUtil.extractText(GetterUtil.getString(text));
}
private void _refreshUpdatesAvailableCache() {
_updateAvailable = null;
}
private void _registerInstalledPluginPackage(PluginPackage pluginPackage)
throws PortalException {
_installedPluginPackages.addPluginPackage(pluginPackage);
_updateAvailable = null;
_indexPluginPackage(pluginPackage);
}
private void _registerPluginPackageInstallation(String preliminaryContext) {
_installedPluginPackages.registerPluginPackageInstallation(
preliminaryContext);
}
private RepositoryReport _reloadRepositories() throws PortalException {
if (_log.isInfoEnabled()) {
_log.info("Reloading repositories");
}
RepositoryReport repositoryReport = new RepositoryReport();
String[] repositoryURLs = _getRepositoryURLs();
for (int i = 0; i < repositoryURLs.length; i++) {
String repositoryURL = repositoryURLs[i];
try {
_loadRepository(repositoryURL);
repositoryReport.addSuccess(repositoryURL);
}
catch (PluginPackageException ppe) {
repositoryReport.addError(repositoryURL, ppe);
_log.error(
"Unable to load repository " + repositoryURL + " " +
ppe.toString());
}
}
Indexer<PluginPackage> indexer = IndexerRegistryUtil.getIndexer(
PluginPackage.class);
indexer.reindex(new String[0]);
return repositoryReport;
}
private Hits _search(
String keywords, String type, String tag, String license,
String repositoryURL, String status, int start, int end)
throws PortalException {
_checkRepositories(repositoryURL);
SearchContext searchContext = new SearchContext();
Map<String, Serializable> attributes = new HashMap<>();
attributes.put("license", license);
attributes.put("repositoryURL", repositoryURL);
attributes.put("status", status);
attributes.put("tag", tag);
attributes.put("type", type);
searchContext.setAttributes(attributes);
searchContext.setCompanyId(CompanyConstants.SYSTEM);
searchContext.setEnd(end);
searchContext.setKeywords(keywords);
QueryConfig queryConfig = new QueryConfig();
queryConfig.setHighlightEnabled(false);
queryConfig.setScoreEnabled(false);
searchContext.setQueryConfig(queryConfig);
searchContext.setStart(start);
Indexer<PluginPackage> indexer = IndexerRegistryUtil.getIndexer(
PluginPackage.class);
return indexer.search(searchContext);
}
private void _unregisterInstalledPluginPackage(PluginPackage pluginPackage)
throws PortalException {
_installedPluginPackages.removePluginPackage(pluginPackage);
try {
List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
pluginPackage.getGroupId(), pluginPackage.getArtifactId());
for (PluginPackage availablePackage : pluginPackages) {
_indexPluginPackage(availablePackage);
}
}
catch (PluginPackageException ppe) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to reindex unistalled package " +
pluginPackage.getContext() + ": " + ppe.getMessage());
}
}
}
private void _updateInstallingPluginPackage(
String preliminaryContext, PluginPackage pluginPackage) {
_installedPluginPackages.unregisterPluginPackageInstallation(
preliminaryContext);
_installedPluginPackages.registerPluginPackageInstallation(
pluginPackage);
}
private static final Log _log = LogFactoryUtil.getLog(
PluginPackageUtil.class);
private static final PluginPackageUtil _instance = new PluginPackageUtil();
private final Set<String> _availableTagsCache;
private final LocalPluginPackageRepository _installedPluginPackages;
private Date _lastUpdateDate;
private final Map<String, RemotePluginPackageRepository> _repositoryCache;
private boolean _settingUpdateAvailable;
private Boolean _updateAvailable;
private class UpdateAvailableRunner implements Runnable {
@Override
public void run() {
try {
setUpdateAvailable();
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e.getMessage());
}
}
}
protected void setUpdateAvailable() throws Exception {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
if (_log.isInfoEnabled()) {
_log.info("Checking for available updates");
}
for (PluginPackage pluginPackage :
_installedPluginPackages.getPluginPackages()) {
PluginPackage availablePluginPackage = null;
if (_isIgnored(pluginPackage)) {
continue;
}
availablePluginPackage =
PluginPackageUtil.getLatestAvailablePluginPackage(
pluginPackage.getGroupId(),
pluginPackage.getArtifactId());
if (availablePluginPackage == null) {
continue;
}
Version availablePluginPackageVersion = Version.getInstance(
availablePluginPackage.getVersion());
if (availablePluginPackageVersion.isLaterVersionThan(
pluginPackage.getVersion())) {
_updateAvailable = Boolean.TRUE;
break;
}
}
if (_updateAvailable == null) {
_updateAvailable = Boolean.FALSE;
}
_settingUpdateAvailable = false;
if (_log.isInfoEnabled()) {
_log.info(
"Finished checking for available updates in " +
stopWatch.getTime() + " ms");
}
}
}
}