/**
* 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.server.manager.internal.executor;
import com.liferay.portal.kernel.deploy.DeployManagerUtil;
import com.liferay.portal.kernel.deploy.auto.context.AutoDeploymentContext;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.plugin.PluginPackage;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.ServerDetector;
import com.liferay.portal.kernel.util.SystemProperties;
import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
import com.liferay.server.manager.internal.constants.JSONKeys;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.osgi.service.component.annotations.Component;
/**
* @author Jonathan Potter
* @author Brian Wing Shun Chan
*/
@Component(
immediate = true,
property = {"server.manager.executor.path=/plugins/plugin"},
service = Executor.class
)
public class PluginExecutor extends BaseExecutor {
@Override
public void executeCreate(
HttpServletRequest request, JSONObject responseJSONObject,
Queue<String> arguments)
throws Exception {
AutoDeploymentContext autoDeploymentContext =
new AutoDeploymentContext();
String context = arguments.poll();
autoDeploymentContext.setContext(context);
File tempFile = getTempFile(request, responseJSONObject);
if (tempFile == null) {
return;
}
autoDeploymentContext.setFile(tempFile);
DeployManagerUtil.deploy(autoDeploymentContext);
boolean success = FileUtils.deleteQuietly(tempFile.getParentFile());
if (success) {
return;
}
String message =
"Unable to remove temp directory " + tempFile.getParentFile();
_log.error(message);
responseJSONObject.put(JSONKeys.ERROR, message);
success = FileUtils.deleteQuietly(tempFile);
if (success) {
return;
}
message = "Unable to remove temp file " + tempFile;
_log.error(message);
responseJSONObject.put(JSONKeys.ERROR, message);
}
@Override
public void executeDelete(
HttpServletRequest request, JSONObject responseJSONObject,
Queue<String> arguments)
throws Exception {
String context = arguments.poll();
DeployManagerUtil.undeploy(context);
}
@Override
public void executeRead(
HttpServletRequest request, JSONObject responseJSONObject,
Queue<String> arguments) {
JSONObject pluginPackageJSONObject = JSONFactoryUtil.createJSONObject();
String context = arguments.poll();
PluginPackage pluginPackage =
DeployManagerUtil.getInstalledPluginPackage(context);
boolean installed = true;
if (pluginPackage == null) {
installed = false;
}
pluginPackageJSONObject.put("installed", installed);
boolean started = true;
if (pluginPackage == null) {
started = false;
}
pluginPackageJSONObject.put("started", started);
List<String> types = new ArrayList<>();
if (pluginPackage != null) {
types = pluginPackage.getTypes();
}
JSONArray typesJSONArray = JSONFactoryUtil.createJSONArray();
for (String type : types) {
typesJSONArray.put(type);
}
pluginPackageJSONObject.put("types", typesJSONArray);
responseJSONObject.put(JSONKeys.OUTPUT, pluginPackageJSONObject);
}
@Override
public void executeUpdate(
HttpServletRequest request, JSONObject responseJSONObject,
Queue<String> arguments)
throws Exception {
String context = arguments.poll();
List<File> installedDirs = getInstalledDirectories(context);
for (File installedDir : installedDirs) {
if (!installedDir.exists()) {
responseJSONObject.put(
JSONKeys.ERROR,
"Context directory " + installedDir.getAbsolutePath() +
" does not exist");
responseJSONObject.put(JSONKeys.STATUS, 1);
return;
}
}
File tempFile = getTempFile(request, responseJSONObject);
if (tempFile == null) {
return;
}
for (File deployDirectory : installedDirs) {
FileUtil.unzip(tempFile, deployDirectory);
}
File partialAppDeletePropsFile = new File(
installedDirs.get(0), "META-INF/liferay-partialapp-delete.props");
if (!partialAppDeletePropsFile.exists()) {
return;
}
BufferedReader bufferedReader = new BufferedReader(
new FileReader(partialAppDeletePropsFile));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
for (File deployDirectory : installedDirs) {
File staleFile = new File(deployDirectory, line.trim());
if (!staleFile.exists()) {
continue;
}
boolean success = FileUtils.deleteQuietly(staleFile);
if (success) {
continue;
}
String message =
"Unable to delete file " + staleFile.getAbsolutePath();
_log.error(message);
responseJSONObject.put(JSONKeys.ERROR, message);
}
}
FileUtils.deleteQuietly(partialAppDeletePropsFile);
if (_log.isInfoEnabled()) {
_log.info("Successfully updated " + context);
}
}
protected FileItem getFileItem(HttpServletRequest request)
throws FileUploadException {
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(
diskFileItemFactory);
List<FileItem> fileItems = servletFileUpload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (!fileItem.isFormField()) {
return fileItem;
}
}
return null;
}
protected File getFileItemTempFile(HttpServletRequest request)
throws Exception {
FileItem fileItem = getFileItem(request);
if (fileItem == null) {
return null;
}
File tempDir = new File(
SystemProperties.get(SystemProperties.TMP_DIR),
PortalUUIDUtil.generate());
if (!tempDir.mkdirs()) {
return null;
}
File tempFile = new File(tempDir, fileItem.getName());
fileItem.write(tempFile);
return tempFile;
}
protected List<File> getInstalledDirectories(final String context)
throws Exception {
List<File> installedDirs = new ArrayList<>();
String installedDirName = DeployManagerUtil.getInstalledDir();
File installedDir = new File(installedDirName, context);
if (installedDir.exists()) {
installedDirs.add(installedDir);
}
else {
File deployWarDir = new File(installedDirName, context + ".war");
installedDirs.add(deployWarDir);
}
if (ServerDetector.isTomcat()) {
File tempDir = new File(
SystemProperties.get(SystemProperties.TMP_DIR));
File[] tempContextDirs = tempDir.listFiles(
new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (name.endsWith("-" + context)) {
return true;
}
return false;
}
});
if (ArrayUtil.isNotEmpty(tempContextDirs)) {
Arrays.sort(
tempContextDirs,
new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
String fileName1 = file1.getName();
String fileName2 = file2.getName();
return fileName1.compareTo(fileName2);
}
});
File tempContextDir = tempContextDirs[
tempContextDirs.length - 1];
installedDirs.add(tempContextDir);
}
}
return installedDirs;
}
protected File getTempFile(
HttpServletRequest request, JSONObject responseJSONObject) {
File tempFile = null;
String message = "Unable to create temp file for uploaded plugin";
try {
tempFile = getFileItemTempFile(request);
}
catch (Exception e) {
_log.error(message, e);
}
if (tempFile != null) {
return tempFile;
}
responseJSONObject.put(JSONKeys.ERROR, message);
responseJSONObject.put(JSONKeys.STATUS, 1);
return null;
}
private static final Log _log = LogFactoryUtil.getLog(PluginExecutor.class);
}