use of org.apache.qpid.qmf2.console.Agent in project qpid by apache.
the class QpidCtrl method main.
/**
* Runs QpidCtrl.
* @param args the command line arguments.
*/
public static void main(final String[] args) {
String logLevel = System.getProperty("amqj.logging.level");
// Set default log level to FATAL rather than DEBUG.
logLevel = (logLevel == null) ? "FATAL" : logLevel;
System.setProperty("amqj.logging.level", logLevel);
// As of Qpid 0.16 the Session Dispatcher Thread is non-Daemon so the JVM gets prevented from exiting.
// Setting the following property to true makes it a Daemon Thread.
System.setProperty("qpid.jms.daemon.dispatcher", "true");
String[] longOpts = { "help", "broker-address=", "class=", "package=", "id=", "agent=", "sasl-mechanism=" };
try {
String host = "localhost";
String connectionOptions = "{reconnect: true}";
String cls = "broker";
String pkg = "org.apache.qpid.broker";
String id = "amqp-broker";
String agentName = "qpidd";
String command = null;
String arg = null;
GetOpt getopt = new GetOpt(args, "ha:c:p:i:v", longOpts);
List<String[]> optList = getopt.getOptList();
String[] cargs = {};
cargs = getopt.getEncArgs().toArray(cargs);
for (String[] opt : optList) {
if (opt[0].equals("-h") || opt[0].equals("--help")) {
System.out.println(_usage);
System.out.println(_options);
System.exit(1);
} else if (opt[0].equals("-a") || opt[0].equals("--broker-address")) {
host = opt[1];
} else if (opt[0].equals("-c") || opt[0].equals("--class")) {
cls = opt[1];
} else if (opt[0].equals("-p") || opt[0].equals("--package")) {
pkg = opt[1];
} else if (opt[0].equals("-i") || opt[0].equals("--id")) {
id = opt[1];
} else if (opt[0].equals("--agent")) {
agentName = opt[1];
} else if (opt[0].equals("-v")) {
System.setProperty("amqj.logging.level", "DEBUG");
} else if (opt[0].equals("--sasl-mechanism")) {
connectionOptions = "{reconnect: true, sasl_mechs: " + opt[1] + "}";
}
}
if (cargs.length < 1 || cargs.length > 2) {
System.out.println(Arrays.asList(cargs));
System.out.println(_usage);
System.exit(1);
}
command = cargs[0];
if (cargs.length == 2) {
arg = cargs[1];
if (!arg.startsWith("{") || !arg.endsWith("}")) {
System.out.println("Incorrect format for args.");
System.out.println("This needs to be in a Stringified Map format similar to an Address String");
System.exit(1);
}
}
QpidCtrl qpidCtrl = new QpidCtrl(host, connectionOptions, pkg, cls, id, agentName, command, arg);
} catch (IllegalArgumentException e) {
System.out.println(_usage);
System.out.println(e.getMessage());
System.exit(1);
}
}
use of org.apache.qpid.qmf2.console.Agent in project qpid by apache.
the class QpidServer method doGet.
/**
* Called by the Web Server to allow a Server to handle a GET request.
* The HTTP GET URL structure for the REST API is specified above in the overall class documentation.
*
* @param tx the HttpTransaction containing the request from the client and used to send the response.
*/
public void doGet(final HttpTransaction tx) throws IOException {
String path = tx.getRequestURI();
if (path.startsWith("/qpid/connection/")) {
path = path.substring(17);
// Using the principal lets different users use the default connection.
String user = tx.getPrincipal();
if (path.length() == 0) {
// handle "/qpid/connection/" request with unspecified connection (returns list of available connections).
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(_connections.getAll(user)));
} else {
// if path.length() > 0 we're dealing with a specified Connection so extract the name and look it up.
String connectionName = path;
int i = path.indexOf("/");
if (// Can use > rather than >= as we've already tested for "/qpid/connection/" above.
i > 0) {
connectionName = path.substring(0, i);
path = path.substring(i + 1);
} else {
path = "";
}
connectionName = user + "." + connectionName;
// attempts to connect to a broker specified in the QpidRestAPI config (or default 0.0.0.0:5672).
if (connectionName.equals(user + ".default")) {
ConnectionProxy defaultConnection = _connections.get(connectionName);
if (defaultConnection == null) {
defaultConnection = _connections.create(connectionName, _defaultBroker, "", false);
// Wait a maximum of 1000ms for the underlying Qpid Connection to become available. If we
// don't do this the first call using the default will return 404 Not Found.
defaultConnection.waitForConnection(1000);
}
}
// Find the Connection with the name extracted from the URI.
ConnectionProxy connection = _connections.get(connectionName);
if (connection == null) {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
} else if (!connection.isConnected()) {
tx.sendResponse(HTTP_INTERNAL_ERROR, "text/plain", "500 Broker Disconnected.");
} else {
if (path.length() == 0) {
// handle request for information about a specified Console
tx.sendResponse(HTTP_OK, "application/json", connection.toString());
} else {
// In this block we are dealing with resources associated with a specified connectionName.
// path describes the resources specifically related to "/qpid/connection/<connectionName>"
Console console = connection.getConsole();
if (path.startsWith("console/objects/")) {
// Get information about specified objects.
path = path.substring(16);
sendGetObjectsResponse(tx, console, path);
} else if (path.startsWith("console/objects") && path.length() == 15) {
// If objects is unspecified treat as a synonym for classes.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getClasses()));
} else if (path.startsWith("console/address/")) {
// Get the Console AMQP Address
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getAddress()));
} else if (path.startsWith("console/address") && path.length() == 15) {
// Get the Console AMQP Address
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getAddress()));
} else if (path.startsWith("console/workItemCount/")) {
// Returns the count of pending WorkItems that can be retrieved.
tx.sendResponse(HTTP_OK, "text/plain", "" + console.getWorkitemCount());
} else if (path.startsWith("console/workItemCount") && path.length() == 21) {
// Returns the count of pending WorkItems that can be retrieved.
tx.sendResponse(HTTP_OK, "text/plain", "" + console.getWorkitemCount());
} else if (path.startsWith("console/nextWorkItem/")) {
// Obtains the next pending work item, or null if none available.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getNextWorkitem()));
} else if (path.startsWith("console/nextWorkItem") && path.length() == 20) {
// Obtains the next pending work item, or null if none available.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getNextWorkitem()));
} else if (path.startsWith("console/agents") && path.length() == 14) {
// Get information about all available Agents.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getAgents()));
} else if (path.startsWith("console/agent/")) {
// Get information about a specified Agent.
Agent agent = console.getAgent(path.substring(14));
if (agent == null) {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
} else {
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(agent));
}
} else if (path.startsWith("console/agent") && path.length() == 13) {
// If agent is unspecified treat as a synonym for agents.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getAgents()));
} else if (path.startsWith("console/classes/")) {
// Get information about the classes for a specified Agent
// Get Agent name
path = path.substring(16);
// TODO handle getClasses() for specified Agent
tx.sendResponse(HTTP_NOT_IMPLEMENTED, "text/plain", "501 getClasses() for specified Agent not yet implemented.");
} else if (path.startsWith("console/classes") && path.length() == 15) {
// Get information about all the classes for all Agents
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getClasses()));
} else if (path.startsWith("console/packages/")) {
// Get information about the packages for a specified Agent
// Get Agent name
path = path.substring(17);
// TODO handle getPackages() for specified Agent.
tx.sendResponse(HTTP_NOT_IMPLEMENTED, "text/plain", "501 getPackages() for specified Agent not yet implemented.");
} else if (path.startsWith("object/")) {
/**
* This is the REST implementation of getObjects(oid) it is also the equivalent of
* the QmfConsoleData refresh() method where an object can update its state.
* N.B. that the ManagementAgent on the broker appears not to set the timestamp properties
* in the response to this call, which means that they get set to current time in the
* QmfConsoleData, this is OK for _update_ts but not for _create_ts and _delete_ts
* users of this call should be aware of that in their own code.
*/
path = path.substring(7);
// The ObjectId has been passed in the URI, create a real ObjectId
ObjectId oid = new ObjectId(path);
List<QmfConsoleData> objects = console.getObjects(oid);
if (objects.size() == 0) {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
} else {
// Not that in a departure from the QMF2 API this returns the QmfConsoleData object
// rather than a list of size one. Perhaps the APIs should be completely consistent
// but this response seems more convenient.
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(objects.get(0)));
}
} else if (path.startsWith("console/packages") && path.length() == 16) {
// Get information about all the packages for all Agents
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(console.getPackages()));
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
}
}
}
} else if (path.startsWith("/qpid/connection")) {
// handle "/qpid/connection" request with unspecified connection (returns list of available connections).
// Using the principal lets different users use the default connection.
String user = tx.getPrincipal();
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(_connections.getAll(user)));
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
}
use of org.apache.qpid.qmf2.console.Agent in project qpid by apache.
the class QpidServer method doPost.
/**
* Called by the Web Server to allow a Server to handle a POST request.
* <pre>
* POST: <host>:<port>/qpid/connection/<name>/object/<ObjectId>
* HTTP body: {"_method_name":<method>,"_arguments":<inArgs>}
* <method>: A string containing the QMF2 method name e.g. "getLogLevel", "setLogLevel", "create", "delete".
* <inArgs>: A JSON string containing the method arguments e.g. {"level":"debug+:Broker"} for setLogLevel.
* HTTP response: A JSON string containing the response e.g. {"level":"notice+"} for getLogLevel (may be empty).
*
* This method invokes the QMF2 method <method> with arguments <inArgs> on the object <ObjectId>
* </pre>
* @param tx the HttpTransaction containing the request from the client and used to send the response.
*/
@SuppressWarnings("unchecked")
public void doPost(final HttpTransaction tx) throws IOException {
String path = tx.getRequestURI();
if (path.startsWith("/qpid/connection/")) {
path = path.substring(17);
String user = tx.getPrincipal();
String connectionName = path;
int i = path.indexOf("/");
if (// Can use > rather than >= as we've already tested for "/qpid/connection/" above.
i > 0) {
connectionName = user + "." + path.substring(0, i);
path = path.substring(i + 1);
// Find the Connection with the name extracted from the URI.
ConnectionProxy connection = _connections.get(connectionName);
if (connection == null) {
_log.info("QpidServer.doPost path: {} Connection not found.", tx.getRequestURI());
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
} else if (!connection.isConnected()) {
tx.sendResponse(HTTP_INTERNAL_ERROR, "text/plain", "500 Broker Disconnected.");
} else {
// If we get this far we should have found a Qpid Connection so retrieve the QMF2 Console Object.
Console console = connection.getConsole();
if (path.startsWith("object/")) {
path = path.substring(7);
// The ObjectId has been passed in the URI create an ObjectId and retrieve the Agent Name.
ObjectId oid = new ObjectId(path);
String agentName = oid.getAgentName();
// The qpidd ManagementAgent doesn't populate AgentName, if it's empty assume it's the broker.
agentName = agentName.equals("") ? "broker" : agentName;
// Find the Agent we got the QmfData from.
Agent agent = console.getAgent(agentName);
if (agent == null) {
_log.info("QpidServer.doPost path: {} Agent: {} not found.", tx.getRequestURI(), agentName);
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
} else {
// If we get this far we can create the Object and invoke the method.
// We can create a QmfConsoleData with nothing but an ObjectId and the agent.
QmfConsoleData object = new QmfConsoleData(Collections.EMPTY_MAP, agent);
object.setObjectId(oid);
String request = tx.getRequestString();
_log.info("QpidServer.doPost path: {} body: {}", tx.getRequestURI(), request);
//System.out.println(request);
String method = "";
try {
Map<String, Object> reqMap = JSON.toMap(request);
method = (String) reqMap.get("_method_name");
Object arguments = reqMap.get("_arguments");
Map args = (arguments instanceof Map) ? (Map) arguments : null;
//System.out.println("method: " + method + ", args: " + args);
// Parse the args if present into a QmfData (needed by invokeMethod).
QmfData inArgs = (args == null) ? new QmfData() : new QmfData(args);
// Invoke the specified method on the QmfConsoleData we've created.
MethodResult results = null;
_log.info("invokeMethod: {}", request);
results = object.invokeMethod(method, inArgs);
tx.sendResponse(HTTP_OK, "application/json", JSON.fromObject(results));
} catch (QmfException qmfe) {
_log.info("QpidServer.doPost() caught Exception {}", qmfe.getMessage());
tx.sendResponse(HTTP_INTERNAL_ERROR, "text/plain", "invokeMethod(" + method + ") -> " + qmfe.getMessage());
} catch (Exception e) {
_log.info("QpidServer.doPost() caught Exception {}", e.getMessage());
tx.sendResponse(HTTP_INTERNAL_ERROR, "text/plain", "500 " + e.getMessage());
}
}
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
}
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
}
use of org.apache.qpid.qmf2.console.Agent in project qpid by apache.
the class QpidServer method doPut.
/**
* <pre>
* PUT: <host>:<port>/qpid/connection/<name>
* HTTP body: {"url":<url>,"connectionOptions":<connectionOptions>[,"disableEvents":true;]}
* <url>: A string containing an AMQP connection URL as used in the qpid::messaging API.
* <connectionOptions>: A JSON string containing connectionOptions in the form specified in the
* qpid::messaging API.
* </pre>
* Called by the Web Server to allow a Server to handle a PUT request.
* This method creates a Qpid Connection Object with the name <name> using the specified url and options.
* <p>
* The optional disableEvents property is used to start up a QMF Connection which can only
* do synchronous calls such as getObjects() and can't receive Agent updates or QMF2 Events.
* <p>
* N.B. It is possible for the Qpid broker to be unavailable when this method is called so it is actually a
* ConnectionProxy that is created. This method waits for up to 1000ms for the underlying Qpid Connection to
* become available and then returns. Clients should be aware that this method successfully returning only
* implies that the ConnectionProxy is in place and the underlying Qpid Connection may not be available.
* If the broker is down the ConnectionProxy will periodically attempt to reconnect, but whilst it is down
* the REST API will return a 500 Broker Disconnected response to any PUT or POST call.
*
* @param tx the HttpTransaction containing the request from the client and used to send the response.
*/
@SuppressWarnings("unchecked")
public void doPut(final HttpTransaction tx) throws IOException {
String path = tx.getRequestURI();
if (path.startsWith("/qpid/connection/")) {
path = path.substring(17);
String user = tx.getPrincipal();
String request = tx.getRequestString();
_log.info("QpidServer.doPut path: {} body: {}", tx.getRequestURI(), request);
String name = user + "." + path;
try {
// The PUT request is a JSON string containing a url String property and a connectionOptions
// property which is itself a JSON String.
Map<String, String> reqMap = JSON.toMap(request);
String url = reqMap.get("url");
url = url.equals("") ? _defaultBroker : url;
// Extract the connectionOptions property and check its type is a MAP
Object options = reqMap.get("connectionOptions");
Map optionsMap = (options instanceof Map) ? (Map) options : null;
// Turn the connectionOptions Map back into a JSON String. Note that we can't just get
// connectionOptions as a String from reqMap as it is sent as JSON and the JSON.toMap()
// call on the POST request will fully parse it.
String connectionOptions = JSON.fromObject(optionsMap);
boolean disableEvents = false;
String disableEventsString = reqMap.get("disableEvents");
if (disableEventsString != null) {
disableEvents = disableEventsString.equalsIgnoreCase("true");
}
ConnectionProxy proxy = _connections.create(name, url, connectionOptions, disableEvents);
// Wait a maximum of 1000ms for the underlying Qpid Connection to become available then return.
proxy.waitForConnection(1000);
tx.sendResponse(HTTP_CREATED, "text/plain", "201 Created.");
} catch (Exception e) {
_log.info("QpidServer.doPut() caught Exception {}", e.getMessage());
tx.sendResponse(HTTP_INTERNAL_ERROR, "text/plain", "500 " + e.getMessage());
}
} else {
tx.sendResponse(HTTP_NOT_FOUND, "text/plain", "404 Not Found.");
}
}
use of org.apache.qpid.qmf2.console.Agent in project qpid by apache.
the class AgentExternalTest method setupSchema.
public void setupSchema() throws QmfException {
System.out.println("*** AgentExternalTest initialising the various Schema classes ***");
// Create and register schema for this agent.
String packageName = "com.profitron.gizmo";
// Declare a schema for a structured exception that can be used in failed method invocations.
_exceptionSchema = new SchemaObjectClass(packageName, "exception");
_exceptionSchema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
_exceptionSchema.addProperty(new SchemaProperty("howBad", QmfType.TYPE_INT));
_exceptionSchema.addProperty(new SchemaProperty("details", QmfType.TYPE_MAP));
// Declare a control object to test methods against.
_controlSchema = new SchemaObjectClass(packageName, "control");
_controlSchema.addProperty(new SchemaProperty("state", QmfType.TYPE_STRING));
_controlSchema.addProperty(new SchemaProperty("methodCount", QmfType.TYPE_INT));
_controlSchema.addProperty(new SchemaProperty("offset", QmfType.TYPE_INT));
_controlSchema.setIdNames("state");
SchemaMethod stopMethod = new SchemaMethod("stop", "Stop Agent");
stopMethod.addArgument(new SchemaProperty("message", QmfType.TYPE_STRING, "{dir:IN}"));
_controlSchema.addMethod(stopMethod);
SchemaMethod echoMethod = new SchemaMethod("echo", "Echo Arguments");
echoMethod.addArgument(new SchemaProperty("message", QmfType.TYPE_STRING, "{dir:INOUT}"));
_controlSchema.addMethod(echoMethod);
SchemaMethod eventMethod = new SchemaMethod("event", "Raise an Event");
eventMethod.addArgument(new SchemaProperty("text", QmfType.TYPE_STRING, "{dir:IN}"));
eventMethod.addArgument(new SchemaProperty("severity", QmfType.TYPE_INT, "{dir:IN}"));
_controlSchema.addMethod(eventMethod);
SchemaMethod failMethod = new SchemaMethod("fail", "Expected to Fail");
failMethod.addArgument(new SchemaProperty("useString", QmfType.TYPE_BOOL, "{dir:IN}"));
failMethod.addArgument(new SchemaProperty("stringVal", QmfType.TYPE_STRING, "{dir:IN}"));
failMethod.addArgument(new SchemaProperty("details", QmfType.TYPE_MAP, "{dir:IN}"));
_controlSchema.addMethod(failMethod);
SchemaMethod createMethod = new SchemaMethod("create_child", "Create Child Object");
createMethod.addArgument(new SchemaProperty("name", QmfType.TYPE_STRING, "{dir:IN}"));
createMethod.addArgument(new SchemaProperty("childAddr", QmfType.TYPE_MAP, "{dir:OUT}"));
_controlSchema.addMethod(createMethod);
// Declare the child class
_childSchema = new SchemaObjectClass(packageName, "child");
_childSchema.addProperty(new SchemaProperty("name", QmfType.TYPE_STRING));
_childSchema.setIdNames("name");
// Declare the event class
_eventSchema = new SchemaEventClass(packageName, "event");
_eventSchema.addProperty(new SchemaProperty("text", QmfType.TYPE_STRING));
System.out.println("AgentExternalTest Schema classes initialised OK");
_agent.registerObjectClass(_exceptionSchema);
_agent.registerObjectClass(_controlSchema);
_agent.registerObjectClass(_childSchema);
_agent.registerEventClass(_eventSchema);
System.out.println("AgentExternalTest Schema classes registered OK");
}
Aggregations