/* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat, Inc., and others contributors as indicated * by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.jboss.narayana.blacktie.btadmin; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import javax.management.MalformedObjectNameException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jboss.narayana.blacktie.administration.BlacktieAdministration; import org.jboss.narayana.blacktie.jatmibroker.core.conf.ConfigurationException; import org.jboss.narayana.blacktie.jatmibroker.core.conf.XMLParser; import org.jboss.narayana.blacktie.jatmibroker.xatmi.Connection; import org.jboss.narayana.blacktie.jatmibroker.xatmi.ConnectionException; import org.jboss.narayana.blacktie.jatmibroker.xatmi.ConnectionFactory; import org.jboss.narayana.blacktie.jatmibroker.xatmi.Response; import org.jboss.narayana.blacktie.jatmibroker.xatmi.X_OCTET; import org.jboss.narayana.blacktie.jatmibroker.xatmi.impl.BufferImpl; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Handle the command */ public class CommandHandler implements java.lang.reflect.InvocationHandler { private static Logger log = LogManager.getLogger(CommandHandler.class); private Properties prop = new Properties(); private Connection connection; private BlacktieAdministration administrationProxy; public CommandHandler() throws ConfigurationException, MalformedObjectNameException, NullPointerException { // Obtain the JMXURL from the btconfig.xml XMLParser.loadProperties("btconfig.xsd", "btconfig.xml", prop); administrationProxy = (BlacktieAdministration) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { BlacktieAdministration.class }, this); } public int handleCommand(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { int exitStatus = -1; if (args.length < 1 || args[0] == null || args[0].trim().length() == 0) { log.error("No command was provided"); } else { Command command = loadCommand(args[0]); // Create an new array for the commands arguments String[] commandArgs = new String[args.length - 1]; if (commandArgs.length > 0) { log.trace("Copying arguments for the command"); System.arraycopy(args, 1, commandArgs, 0, commandArgs.length); } String quickstartUsage = command.getQuickstartUsage(); char[] charArray = quickstartUsage.toCharArray(); int expectedArgsLength = 0; int optionalArgs = 0; // Note this does assume that each word is a parameter for (int i = 0; i < quickstartUsage.length(); i++) { if (charArray[i] == ' ') { expectedArgsLength++; } else if (charArray[i] == '[') { optionalArgs++; } } // Add the last parameter if (charArray.length > 0) { expectedArgsLength++; } // Check if the number of parameters is in an expected range if (commandArgs.length > expectedArgsLength || commandArgs.length < expectedArgsLength - optionalArgs) { if (optionalArgs == 0) { log.trace("Arguments incompatible, expected " + expectedArgsLength + ", received: " + commandArgs.length); } else { log.trace("Arguments incompatible, expected at least " + optionalArgs + " and no more than " + expectedArgsLength + ", received: " + commandArgs.length); } log.error(("Expected Usage: " + args[0] + " " + quickstartUsage).trim()); } else { try { // Try to initialize the arguments command.initializeArgs(commandArgs); log.trace("Arguments initialized"); try { // Try to invoke the command command.invoke(administrationProxy, prop); exitStatus = 0; log.trace("Command invoked"); } catch (CommandFailedException e) { exitStatus = e.getExitCode(); } catch (Exception e) { log.error("Could not invoke the command: " + e.getMessage(), e); } } catch (IncompatibleArgsException e) { String usage = "Expected Usage: " + args[0] + " " + quickstartUsage; log.error("Arguments invalid: " + e.getMessage()); log.error(usage.trim()); log.trace("Arguments invalid: " + e.getMessage(), e); } } } return exitStatus; } public static Command loadCommand(String commandName) throws InstantiationException, IllegalAccessException, ClassNotFoundException { String firstLetter = commandName.substring(0, 1); String remainder = commandName.substring(1); String capitalized = firstLetter.toUpperCase() + remainder; String className = "org.jboss.narayana.blacktie.btadmin.commands." + capitalized; log.debug("Will execute the " + className + " command"); Command command = (Command) Class.forName(className).newInstance(); log.debug("Command was known"); return command; } /** * Utility function to output the list * * @param operationName * @param list */ public static String convertList(String operationName, List list) { StringBuffer buffer = new StringBuffer(); buffer.append("Output from: " + operationName); int i = 0; Iterator iterator = list.iterator(); while (iterator.hasNext()) { buffer.append("\nElement: " + i + " Value: " + iterator.next()); i++; } return buffer.toString(); } public Object invoke(Object proxy, Method method, Object[] args) throws ConfigurationException, ConnectionException, CommandFailedException, ParserConfigurationException, SAXException, IOException { if (connection == null) { ConnectionFactory cf = ConnectionFactory.getConnectionFactory(); connection = cf.getConnection(); } StringBuffer command = new StringBuffer(method.getName()); command.append(','); if (args != null) { for (int i = 0; i < args.length; i++) { if (args[i] == null) { args[i] = ""; } command.append(args[i].toString()); command.append(','); } } X_OCTET sendbuf = (X_OCTET) connection.tpalloc("X_OCTET", null); sendbuf.setByteArray(command.toString().getBytes()); Response received = connection.tpcall("BTDomainAdmin", sendbuf, 0); X_OCTET rcvbuf = (X_OCTET) received.getBuffer(); Class<?> returnType = method.getReturnType(); byte[] byteArray = rcvbuf.getByteArray(); ; if (returnType == Boolean.class) { if (byteArray[0] == 1) { return true; } else { return false; } } else if (returnType == Long.class) { return convertLong(byteArray); } else if (returnType == String.class) { return new String(byteArray); } else if (returnType == java.util.List.class) { String listTerminator = BlacktieAdministration.LIST_TERMINATOR; String string = new String(byteArray); StringTokenizer outParameters = new StringTokenizer(string, "," + "", false); if (!method.getName().equals("listRunningInstanceIds")) { List<String> toReturn = new ArrayList<String>(); while (outParameters.hasMoreTokens()) { String nextToken = outParameters.nextToken(); if (!nextToken.equals(listTerminator)) { toReturn.add(nextToken); } } return toReturn; } else { List<Integer> toReturn = new ArrayList<Integer>(); while (outParameters.hasMoreTokens()) { String nextToken = outParameters.nextToken(); if (!nextToken.equals(listTerminator)) { toReturn.add(Integer.parseInt(nextToken)); } } return toReturn; } } else if (returnType == org.w3c.dom.Element.class) { StringReader sreader = new StringReader(new String(byteArray)); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(new InputSource(sreader)); return doc.getDocumentElement(); } else { log.error("Could not handle response type: " + returnType); throw new CommandFailedException(-1); } // java.util.List<Integer> } private long convertLong(byte[] response) throws IOException { ByteArrayInputStream baos = new ByteArrayInputStream(response); DataInputStream dos = new DataInputStream(baos); ByteBuffer bbuf = ByteBuffer.allocate(BufferImpl.LONG_SIZE); bbuf.order(ByteOrder.BIG_ENDIAN); bbuf.put(response); bbuf.order(ByteOrder.LITTLE_ENDIAN); return bbuf.getLong(0); } }