/*
* Copyright (c) Members of the EGEE Collaboration. 2006-2010.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.glite.authz.common.http;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.glite.authz.common.util.Strings;
import org.opensaml.ws.soap.client.http.HttpClientBuilder;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
/**
* A command line tool used to communicate with {@link JettyAdminService}.
*
* Command line arguments are, in order:
* <ul>
* <li><em>hostname</em> - hostname to which to connect</li>
* <li><em>port</em> - port to which to connect</li>
* <li><em>command</em> - admin command to execute</li>
* <li><em>password</em> - admin command password</li>
* </ul>
*/
public class JettyAdminServiceCLI {
/** Successful return code: {@value} . */
public static final int RC_SUCCESS = 0;
/** Bad command line arguments return code: {@value} . */
public static final int RC_BAD_ARGUMENTS = 1;
/** HTTP connection error return code: {@value} . */
public static final int RC_CTX = 2;
/** Invalid command return code: {@value} . */
public static final int RC_INVALID_COMMAND = 3;
/** Unauthorized return code: {@value} . */
public static final int RC_UNAUTHORIZED = 4;
/** Unknown error return code: {@value} . */
public static final int RC_UNKNOWN = 100;
/**
* Run the admin client.
*
* @param args command line arguments
*/
public static void main(String[] args) {
if (args.length < 3) {
exit("Invalid command line arguments", RC_BAD_ARGUMENTS);
}
disableLibraryLogging();
String host = parseHost(args[0]);
int port = parsePort(args[1]);
String command = parseCommand(args[2]);
String password = null;
if(args.length == 4){
password = Strings.safeTrimOrNullString(args[3]);
}
executeCommand(host, port, command, password);
exit(null, RC_SUCCESS);
}
/** Disables logging messages from all dependent libraries. */
private static void disableLibraryLogging() {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger rootLogger = lc.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.OFF);
}
/**
* Parses the hostname command line argument. Checks that the argument is a valid hostname.
*
* @param hostArgument the command line hostname argument
*
* @return the hostname
*/
private static String parseHost(String hostArgument) {
try {
InetAddress[] addresses = InetAddress.getAllByName(hostArgument);
return addresses[0].getHostName();
} catch (UnknownHostException e) {
exit("The host argument is not a valid hostname or IP address", RC_BAD_ARGUMENTS);
}
return null;
}
/**
* Parses the port command line argument. Checks that the port command line argument is a valid integer and between
* 1 and 65535 (valid port numbers).
*
* @param portArgument the command line port argument
*
* @return the port
*/
private static int parsePort(String portArgument) {
try {
int port = Integer.parseInt(portArgument);
if (port < 1 || port > 65535) {
exit("Port number is not valid", RC_BAD_ARGUMENTS);
}
return port;
} catch (NumberFormatException e) {
exit("Port number is not valid", RC_BAD_ARGUMENTS);
}
return 0;
}
/**
* Parses the command command line argument. Checks that the argument is not null.
*
* @param commandArgument the command line command argument
*
* @return the command
*/
private static String parseCommand(String commandArgument) {
String argument = Strings.safeTrimOrNullString(commandArgument);
if (argument == null) {
exit("Command argument is not valid", RC_BAD_ARGUMENTS);
}
return argument;
}
/**
* Executes the service command. Also checks to ensure the HTTP return code was 200.
*
* @param host host to which to connect
* @param port port to which to connect
* @param command command sent to the admin service
* @param password admin command password, may be null
*/
private static void executeCommand(String host, int port, String command, String password) {
HttpClientBuilder clientBuilder = new HttpClientBuilder();
HttpClient httpClient = clientBuilder.buildClient();
GetMethod getMethod = new GetMethod("http://" + host + ":" + port + "/" + command);
if (password != null) {
getMethod.setQueryString(new NameValuePair[] { new NameValuePair(PasswordProtectFilter.PASSWORD_PARAM_NAME,
password), });
}
try {
httpClient.executeMethod(getMethod);
String response = Strings.safeTrimOrNullString(getMethod.getResponseBodyAsString());
if(response != null){
System.out.println(response);
}
} catch (ConnectException e) {
exit("Unable to connect to " + host + ":" + port + ", perhaps the service is not running", RC_CTX);
} catch (IOException e) {
exit("Error executing service command:\n" + e.getMessage(), RC_CTX);
}
int statusCode = getMethod.getStatusCode();
if (statusCode == HttpStatus.SC_OK){
return;
}else if(statusCode == HttpStatus.SC_UNAUTHORIZED){
exit("you are not authorized to execute admin commands; invalid password", RC_UNAUTHORIZED);
}else{
exit("Service returned unexpected HTTP status code; " + statusCode, RC_UNKNOWN);
}
}
/**
* Prints the given message to STDERR and exits with the given status code.
*
* @param message the message to output, may be null if nothing is to be printed
* @param returnCode the return code to be given for the application
*/
private static void exit(String message, int returnCode) {
if (message != null) {
System.err.println(message);
}
System.exit(returnCode);
}
}