/*
* Tigase Jabber/XMPP Server
* Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://www.gnu.org/licenses/.
*
* $Rev$
* Last modified by $Author$
* $Date$
*/
package tigase.server.script;
//~--- non-JDK imports --------------------------------------------------------
import tigase.server.CmdAcl;
import tigase.server.Command;
import tigase.server.Iq;
import tigase.server.Packet;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.Bindings;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
//~--- classes ----------------------------------------------------------------
/**
* Created: Jan 2, 2009 2:29:48 PM
*
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev$
*/
public class AddScriptCommand extends AbstractScriptCommand {
private static final Logger log = Logger.getLogger(AddScriptCommand.class.getName());
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param cmdId
* @param cmdDescr
* @param script
* @param lang
* @param ext
* @param binds
*
* @return
*
* @throws ScriptException
*/
@SuppressWarnings({ "unchecked" })
public Script addAdminScript(String cmdId, String cmdDescr, String script, String lang,
String ext, Bindings binds)
throws ScriptException {
Script as = new Script();
as.init(cmdId, cmdDescr, script, lang, ext, binds);
Map<String, CommandIfc> adminCommands = (Map<String, CommandIfc>) binds.get(ADMN_CMDS);
adminCommands.put(as.getCommandId(), as);
Map<String, EnumSet<CmdAcl>> commandsACL = (Map<String,
EnumSet<CmdAcl>>) binds.get(COMMANDS_ACL);
EnumSet<CmdAcl> acl = commandsACL.get(as.getCommandId());
if (acl != null) {
for (CmdAcl cmdAcl : acl) {
if (cmdAcl != CmdAcl.ADMIN) {
as.setAdminOnly(false);
break;
}
}
}
// ServiceEntity serviceEntity = (ServiceEntity) binds.get(ADMN_DISC);
// ServiceEntity item = new ServiceEntity(as.getCommandId(),
// "http://jabber.org/protocol/admin#" + as.getCommandId(),
// cmdDescr);
// item.addIdentities(
// new ServiceIdentity("component", "generic", cmdDescr),
// new ServiceIdentity("automation", "command-node", cmdDescr));
// item.addFeatures(XMPPService.CMD_FEATURES);
// serviceEntity.addItems(item);
return as;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public Bindings getBindings() {
return null;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param packet
* @param binds
* @param results
*/
@Override
@SuppressWarnings({ "unchecked" })
public void runCommand(Iq packet, Bindings binds, Queue<Packet> results) {
String language = Command.getFieldValue(packet, LANGUAGE);
String commandId = Command.getFieldValue(packet, COMMAND_ID);
String description = Command.getFieldValue(packet, DESCRIPT);
String[] scriptText = Command.getFieldValues(packet, SCRIPT_TEXT);
boolean saveToDisk = Command.getCheckBoxFieldValue(packet, SAVE_TO_DISK);
if (isEmpty(language) || isEmpty(commandId) || isEmpty(description) || (scriptText == null)) {
results.offer(prepareScriptCommand(packet, binds));
} else {
StringBuilder sb = new StringBuilder(1024);
for (String string : scriptText) {
if (string != null) {
sb.append(string).append("\n");
}
}
try {
Script s = addAdminScript(commandId, description, sb.toString(), language, null, binds);
Packet result = packet.commandResult(Command.DataType.result);
Command.addTextField(result, "Note", "Script loaded successfuly.");
results.offer(result);
if (saveToDisk) {
saveCommandToDisk(commandId, description, sb, s.getFileExtension(), binds);
}
} catch (Exception e) {
log.log(Level.WARNING, "Can't initialize script: ", e);
Packet result = packet.commandResult(Command.DataType.result);
Command.addTextField(result, "Note", "Script initialization error.");
StackTraceElement[] ste = e.getStackTrace();
String[] error = new String[ste.length + 2];
error[0] = e.getMessage();
error[1] = e.toString();
for (int i = 0; i < ste.length; i++) {
error[i + 2] = ste[i].toString();
}
Command.addTextField(result, "Error message", e.getMessage());
Command.addFieldMultiValue(result, "Debug info", Arrays.asList(error));
results.offer(result);
}
}
}
private Packet prepareScriptCommand(Iq packet, Bindings binds) {
Packet result = packet.commandResult(Command.DataType.form);
Command.addFieldValue(result, DESCRIPT, "Short description");
Command.addFieldValue(result, COMMAND_ID, "new-command");
ScriptEngineManager scriptEngineManager = (ScriptEngineManager) binds.get(SCRI_MANA);
List<ScriptEngineFactory> scriptFactories = scriptEngineManager.getEngineFactories();
if (scriptFactories != null) {
String[] langs = new String[scriptFactories.size()];
int idx = 0;
String def = null;
for (ScriptEngineFactory scriptEngineFactory : scriptFactories) {
langs[idx++] = scriptEngineFactory.getLanguageName();
if (scriptEngineFactory.getLanguageName().equals("groovy")) {
def = "groovy";
}
}
if (def == null) {
def = langs[0];
}
Command.addFieldValue(result, LANGUAGE, def, LANGUAGE, langs, langs);
}
Command.addFieldMultiValue(result, SCRIPT_TEXT, Collections.nCopies(1, ""));
Command.addCheckBoxField(result, SAVE_TO_DISK, true);
return result;
}
private void saveCommandToDisk(String commandId, String description, StringBuilder sb,
String fileExtension, Bindings binds)
throws IOException {
File fileName = new File((String) binds.get(SCRIPT_COMP_DIR), commandId + "." + fileExtension);
log.log(Level.INFO, "Saving command: {0} to disk file: {1}", new Object[] { commandId,
fileName.toString() });
FileWriter fw = new FileWriter(fileName, false);
String comment = lineCommentStart.get(fileExtension);
if (comment == null) {
comment = "//";
}
fw.write(comment + " " + SCRIPT_DESCRIPTION + " " + description + '\n');
fw.write(comment + " " + SCRIPT_ID + " " + commandId + '\n');
fw.write(comment + " " + SCRIPT_COMPONENT + " " + binds.get(COMPONENT_NAME) + '\n');
fw.write(sb.toString());
fw.close();
}
}
//~ Formatted in Sun Code Convention
//~ Formatted by Jindent --- http://www.jindent.com