/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.agent.promptcmd;
import java.io.File;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import mazz.i18n.Msg;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
import org.rhq.core.clientapi.server.core.CoreServerService;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.agent.AgentMain;
import org.rhq.enterprise.agent.PluginUpdate;
import org.rhq.enterprise.agent.i18n.AgentI18NFactory;
import org.rhq.enterprise.agent.i18n.AgentI18NResourceKeys;
import org.rhq.enterprise.communications.command.client.ClientCommandSender;
import org.rhq.enterprise.communications.command.client.ClientRemotePojoFactory;
/**
* Allows you to manually update the plugins.
*
* @author John Mazzitelli
*/
public class PluginsPromptCommand implements AgentPromptCommand {
private static final Msg MSG = AgentI18NFactory.getMsg();
/**
* @see AgentPromptCommand#getPromptCommandString()
*/
public String getPromptCommandString() {
return MSG.getMsg(AgentI18NResourceKeys.PLUGINS);
}
/**
* @see AgentPromptCommand#execute(AgentMain, String[])
*/
public boolean execute(AgentMain agent, String[] args) {
PrintWriter out = agent.getOut();
if (args.length != 2) {
out.println(MSG.getMsg(AgentI18NResourceKeys.HELP_SYNTAX_LABEL, getSyntax()));
return true;
}
try {
if (args[1].equals(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_ARG_UPDATE))) {
doUpdate(agent);
} else if (args[1].equals(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_ARG_INFO))) {
doInfo(agent);
} else {
out.println(MSG.getMsg(AgentI18NResourceKeys.HELP_SYNTAX_LABEL, getSyntax()));
}
} catch (Exception e) {
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_ERROR_UPDATING, ThrowableUtil.getAllMessages(e)));
}
return true;
}
/**
* @see AgentPromptCommand#getSyntax()
*/
public String getSyntax() {
return MSG.getMsg(AgentI18NResourceKeys.PLUGINS_SYNTAX);
}
/**
* @see AgentPromptCommand#getHelp()
*/
public String getHelp() {
return MSG.getMsg(AgentI18NResourceKeys.PLUGINS_HELP);
}
/**
* @see AgentPromptCommand#getDetailedHelp()
*/
public String getDetailedHelp() {
return MSG.getMsg(AgentI18NResourceKeys.PLUGINS_DETAILED_HELP);
}
/**
* Performs the info command which will output information on the currently installed plugins to the agent's output.
*
* @param agent
*
* @throws Exception
*/
private void doInfo(AgentMain agent) throws Exception {
PrintWriter out = agent.getOut();
PluginUpdate plugin_update = getPluginUpdateObject(agent);
List<File> current_plugins = plugin_update.getCurrentPluginFiles();
List<String> disabled_plugins = plugin_update.getPluginContainerConfiguration().getDisabledPlugins();
List<String> installed_plugins = new ArrayList<String>();
if (current_plugins.size() > 0) {
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_LISTING_PLUGINS_DETAILS));
for (File current_plugin : current_plugins) {
String plugin_name;
String plugin_display_name;
try {
URL url = current_plugin.toURI().toURL();
PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(url);
plugin_name = descriptor.getName();
plugin_display_name = descriptor.getDisplayName();
installed_plugins.add(plugin_name);
} catch (Throwable t) {
plugin_name = "?cannot-parse-descriptor?";
plugin_display_name = "?cannot-parse-descriptor?";
}
String filename = current_plugin.getName();
Date last_mod = new Date(current_plugin.lastModified());
long filesize = current_plugin.length();
String md5 = MessageDigestGenerator.getDigestString(current_plugin);
out.println();
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_FILENAME, filename));
out.print('\t');
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_NAME, plugin_name));
out.print('\t');
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_DISPLAY_NAME, plugin_display_name));
out.print('\t');
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_LASTMOD, last_mod));
out.print('\t');
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_FILESIZE, filesize));
out.print('\t');
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_PLUGINS_INFO_MD5, md5));
}
out.println();
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_LISTING_PLUGINS_SUMMARY, installed_plugins));
if (!disabled_plugins.isEmpty()) {
out.println();
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_LISTING_PLUGINS_DISABLED, disabled_plugins));
}
out.println();
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_NUM_CURRENT_PLUGINS, current_plugins.size()));
} else {
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_NO_CURRENT_PLUGINS));
}
return;
}
/**
* Performs the update command which will update all plugins and output to the agent's <code>out</code> stream what
* was updated.
*
* @param agent
*
* @throws Exception
*/
private void doUpdate(AgentMain agent) throws Exception {
// if the PC is already started, we need to shut it down and restart it after we get the new plugins
boolean recyclePC = agent.isPluginContainerStarted();
PrintWriter out = agent.getOut();
// make sure our agent is currently in communications with the server
ClientCommandSender clientCommandSender = agent.getClientCommandSender();
if (clientCommandSender == null || !clientCommandSender.isSending()) {
out.println(MSG.getMsg(AgentI18NResourceKeys.PLUGINS_ERROR_NOT_SENDING));
return;
}
// use the PC prompt command to stop the PC - needed because the PC cannot hot-deploy plugins
if (recyclePC) {
executePCCommand(agent, "stop");
}
// catch any exceptions and keep going so we can restart the PC, even if plugins failed to update
try {
out.println(MSG.getMsg(AgentI18NResourceKeys.UPDATING_PLUGINS));
List<Plugin> updated_plugins = updatePlugins(agent);
if ((updated_plugins != null) && (updated_plugins.size() > 0)) {
for (Plugin plugin : updated_plugins) {
if (plugin.isEnabled()) {
out.println(MSG.getMsg(AgentI18NResourceKeys.DOWNLOADING_PLUGIN_COMPLETE, plugin.getName(),
plugin.getPath()));
} else {
out.println(MSG.getMsg(AgentI18NResourceKeys.DOWNLOADING_PLUGIN_SKIPPED, plugin.getName()));
}
}
} else {
out.println(MSG.getMsg(AgentI18NResourceKeys.UPDATING_PLUGINS_ALREADY_UPTODATE));
}
out.println(MSG.getMsg(AgentI18NResourceKeys.UPDATING_PLUGINS_COMPLETE));
} catch (Throwable t) {
out.println(MSG.getMsg(AgentI18NResourceKeys.UPDATING_PLUGINS_FAILURE));
out.println(ThrowableUtil.getAllMessages(t));
}
if (recyclePC) {
executePCCommand(agent, "start");
}
return;
}
/**
* Updates plugins with their latest versions. If our plugins are already up-to-date, this leaves them as-is.
*
* @param agent
*
* @return the list of plugins that were updated (those not listed were already up-to-date)
*
* @throws Exception if failed to update the plugins
*/
private List<Plugin> updatePlugins(AgentMain agent) throws Exception {
return getPluginUpdateObject(agent).updatePlugins();
}
/**
* Builds a {@link PluginUpdate} object that can be used to update the plugins.
*
* @param agent
*
* @return plugin updater
*/
private PluginUpdate getPluginUpdateObject(AgentMain agent) {
ClientCommandSender sender = agent.getClientCommandSender();
CoreServerService server = null;
if (sender != null) {
ClientRemotePojoFactory factory = sender.getClientRemotePojoFactory();
server = factory.getRemotePojo(CoreServerService.class);
}
PluginContainerConfiguration pc_config = agent.getConfiguration().getPluginContainerConfiguration();
PluginUpdate plugin_update = new PluginUpdate(server, pc_config);
return plugin_update;
}
private void executePCCommand(AgentMain agent, String startOrStop) {
new PluginContainerPromptCommand().execute(agent, new String[] { "pc", startOrStop });
}
}