/**
* 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.marketplace.bundle;
import com.liferay.portal.kernel.deploy.auto.AutoDeployException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.lpkg.deployer.LPKGDeployer;
import com.liferay.portal.lpkg.deployer.LPKGVerifier;
import com.liferay.portal.util.ShutdownUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Version;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Joan Kim
* @author Ryan Park
*/
@Component(immediate = true, service = BundleManager.class)
public class BundleManager {
public Bundle getBundle(String symbolicName, String versionString) {
Version version = Version.parseVersion(versionString);
for (Bundle bundle : getBundles()) {
if (symbolicName.equals(bundle.getSymbolicName()) &&
version.equals(bundle.getVersion())) {
return bundle;
}
}
return null;
}
public List<Bundle> getBundles() {
return ListUtil.fromArray(_bundleContext.getBundles());
}
public List<Bundle> getInstalledBundles() {
List<Bundle> bundles = getBundles();
Iterator<Bundle> itr = bundles.iterator();
while (itr.hasNext()) {
Bundle bundle = itr.next();
if (!isInstalled(bundle)) {
itr.remove();
}
}
return bundles;
}
public Manifest getManifest(File file) {
InputStream inputStream = null;
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
ZipEntry zipEntry = zipFile.getEntry("META-INF/MANIFEST.MF");
if (zipEntry == null) {
return null;
}
inputStream = zipFile.getInputStream(zipEntry);
return new Manifest(inputStream);
}
catch (Exception e) {
}
finally {
StreamUtil.cleanUp(inputStream);
if (zipFile != null) {
try {
zipFile.close();
}
catch (IOException ioe) {
}
}
}
return null;
}
public List<Bundle> installLPKG(File file) throws Exception {
_lpkgVerifier.verify(file);
File installFile = new File(getInstallDirName(), file.getName());
Files.move(
file.toPath(), installFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
if (isRestartRequired(installFile)) {
ShutdownUtil.shutdown(0);
return Collections.emptyList();
}
List<Bundle> bundles = _lpkgDeployer.deploy(
_bundleContext, installFile);
for (int i = 1; i < bundles.size(); i++) {
Bundle bundle = bundles.get(i);
bundle.start();
}
return bundles;
}
public boolean isInstalled(Bundle bundle) {
if (ArrayUtil.contains(_INSTALLED_BUNDLE_STATES, bundle.getState())) {
return true;
}
else {
return false;
}
}
public boolean isInstalled(String symbolicName, String version) {
Bundle bundle = getBundle(symbolicName, version);
if (bundle == null) {
return false;
}
return isInstalled(bundle);
}
public void uninstallBundle(Bundle bundle) {
try {
bundle.uninstall();
}
catch (BundleException be) {
_log.error(be, be);
}
}
public void uninstallBundle(String symbolicName, String version) {
Bundle bundle = getBundle(symbolicName, version);
if (bundle == null) {
return;
}
uninstallBundle(bundle);
}
@Activate
protected void activate(BundleContext bundleContext) {
_bundleContext = bundleContext;
}
protected String getInstallDirName() throws Exception {
String[] autoDeployDirNames = PropsUtil.getArray(
PropsKeys.MODULE_FRAMEWORK_AUTO_DEPLOY_DIRS);
if (ArrayUtil.isEmpty(autoDeployDirNames)) {
throw new AutoDeployException(
"The portal property \"" +
PropsKeys.MODULE_FRAMEWORK_AUTO_DEPLOY_DIRS +
"\" is not set");
}
String autoDeployDirName = autoDeployDirNames[0];
for (String curDirName : autoDeployDirNames) {
if (curDirName.endsWith("/marketplace")) {
autoDeployDirName = curDirName;
break;
}
}
return autoDeployDirName;
}
protected boolean isRestartRequired(File file) {
try (ZipFile zipFile = new ZipFile(file)) {
ZipEntry zipEntry = zipFile.getEntry(
"liferay-marketplace.properties");
if (zipEntry == null) {
return false;
}
Properties properties = new Properties();
properties.load(zipFile.getInputStream(zipEntry));
return GetterUtil.getBoolean(
properties.getProperty("restart-required"), true);
}
catch (Exception e) {
if (_log.isDebugEnabled()) {
_log.debug(
"Unable to read liferay-marketplace.properties from " +
file.getName());
}
}
return false;
}
private static final int[] _INSTALLED_BUNDLE_STATES = {
Bundle.ACTIVE, Bundle.INSTALLED, Bundle.RESOLVED
};
private static final Log _log = LogFactoryUtil.getLog(BundleManager.class);
private BundleContext _bundleContext;
@Reference
private LPKGDeployer _lpkgDeployer;
@Reference
private LPKGVerifier _lpkgVerifier;
}