forked from I2P_Developers/i2p.i2p
264 lines
6.6 KiB
Java
264 lines
6.6 KiB
Java
|
package com.thetransactioncompany.jsonrpc2.server;
|
||
|
|
||
|
|
||
|
import java.util.Hashtable;
|
||
|
|
||
|
import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
|
||
|
import com.thetransactioncompany.jsonrpc2.JSONRPC2Notification;
|
||
|
import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
|
||
|
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Dispatcher for JSON-RPC 2.0 requests and notifications. This class is
|
||
|
* tread-safe.
|
||
|
*
|
||
|
* <p>Use the {@code register()} methods to add a request or notification
|
||
|
* handler for an RPC method.
|
||
|
*
|
||
|
* <p>Use the {@code process()} methods to have an incoming request or
|
||
|
* notification processed by the matching handler.
|
||
|
*
|
||
|
* <p>The {@code reportProcTime()} method enables reporting of request
|
||
|
* processing time (in microseconds) by appending a non-standard "xProcTime"
|
||
|
* attribute to the resulting JSON-RPC 2.0 response message.
|
||
|
*
|
||
|
* <p>Example:
|
||
|
*
|
||
|
* <pre>
|
||
|
* {
|
||
|
* "result" : "xyz",
|
||
|
* "id" : 1,
|
||
|
* "jsonrpc" : "2.0",
|
||
|
* "xProcTime" : "189 us"
|
||
|
* }
|
||
|
* </pre>
|
||
|
*
|
||
|
* <p>Note: The dispatch(...) methods were deprecated in version 1.7. Use
|
||
|
* process(...) instead.
|
||
|
*
|
||
|
* @author Vladimir Dzhuvinov
|
||
|
*/
|
||
|
public class Dispatcher implements RequestHandler, NotificationHandler {
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Hashtable of request name / handler pairs.
|
||
|
*/
|
||
|
private final Hashtable<String,RequestHandler> requestHandlers;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Hashtable of notification name / handler pairs.
|
||
|
*/
|
||
|
private final Hashtable<String,NotificationHandler> notificationHandlers;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Controls reporting of request processing time by appending a
|
||
|
* non-standard "xProcTime" attribute to the JSON-RPC 2.0 response.
|
||
|
*/
|
||
|
private boolean reportProcTime = false;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Creates a new dispatcher with no registered handlers.
|
||
|
*/
|
||
|
public Dispatcher() {
|
||
|
|
||
|
requestHandlers = new Hashtable<String,RequestHandler>();
|
||
|
notificationHandlers = new Hashtable<String,NotificationHandler>();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Registers a new JSON-RPC 2.0 request handler.
|
||
|
*
|
||
|
* @param handler The request handler to register. Must not be
|
||
|
* {@code null}.
|
||
|
*
|
||
|
* @throws IllegalArgumentException On attempting to register a handler
|
||
|
* that duplicates an existing request
|
||
|
* name.
|
||
|
*/
|
||
|
public void register(final RequestHandler handler) {
|
||
|
|
||
|
for (String name: handler.handledRequests()) {
|
||
|
|
||
|
if (requestHandlers.containsKey(name))
|
||
|
throw new IllegalArgumentException("Cannot register a duplicate JSON-RPC 2.0 handler for request " + name);
|
||
|
|
||
|
requestHandlers.put(name, handler);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Registers a new JSON-RPC 2.0 notification handler.
|
||
|
*
|
||
|
* @param handler The notification handler to register. Must not be
|
||
|
* {@code null}.
|
||
|
*
|
||
|
* @throws IllegalArgumentException On attempting to register a handler
|
||
|
* that duplicates an existing
|
||
|
* notification name.
|
||
|
*/
|
||
|
public void register(final NotificationHandler handler) {
|
||
|
|
||
|
for (String name: handler.handledNotifications()) {
|
||
|
|
||
|
if (notificationHandlers.containsKey(name))
|
||
|
throw new IllegalArgumentException("Cannot register a duplicate JSON-RPC 2.0 handler for notification " + name);
|
||
|
|
||
|
notificationHandlers.put(name, handler);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
@Override
|
||
|
public String[] handledRequests() {
|
||
|
|
||
|
java.util.Set<String> var = requestHandlers.keySet();
|
||
|
return var.toArray(new String[var.size()]);
|
||
|
}
|
||
|
|
||
|
|
||
|
@Override
|
||
|
public String[] handledNotifications() {
|
||
|
|
||
|
java.util.Set<String> var = notificationHandlers.keySet();
|
||
|
return var.toArray(new String[var.size()]);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Gets the handler for the specified JSON-RPC 2.0 request name.
|
||
|
*
|
||
|
* @param requestName The request name to lookup.
|
||
|
*
|
||
|
* @return The corresponding request handler or {@code null} if none
|
||
|
* was found.
|
||
|
*/
|
||
|
public RequestHandler getRequestHandler(final String requestName) {
|
||
|
|
||
|
return requestHandlers.get(requestName);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Gets the handler for the specified JSON-RPC 2.0 notification name.
|
||
|
*
|
||
|
* @param notificationName The notification name to lookup.
|
||
|
*
|
||
|
* @return The corresponding notification handler or {@code null} if
|
||
|
* none was found.
|
||
|
*/
|
||
|
public NotificationHandler getNotificationHandler(final String notificationName) {
|
||
|
|
||
|
return notificationHandlers.get(notificationName);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @deprecated
|
||
|
*/
|
||
|
public JSONRPC2Response dispatch(final JSONRPC2Request request, final MessageContext requestCtx) {
|
||
|
|
||
|
return process(request, requestCtx);
|
||
|
}
|
||
|
|
||
|
|
||
|
@Override
|
||
|
public JSONRPC2Response process(final JSONRPC2Request request, final MessageContext requestCtx) {
|
||
|
|
||
|
long startNanosec = 0;
|
||
|
|
||
|
// Measure request processing time?
|
||
|
if (reportProcTime)
|
||
|
startNanosec = System.nanoTime();
|
||
|
|
||
|
|
||
|
final String method = request.getMethod();
|
||
|
|
||
|
RequestHandler handler = getRequestHandler(method);
|
||
|
|
||
|
if (handler == null) {
|
||
|
|
||
|
// We didn't find a handler for the requested RPC
|
||
|
|
||
|
Object id = request.getID();
|
||
|
|
||
|
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, id);
|
||
|
}
|
||
|
|
||
|
// Process the request
|
||
|
|
||
|
JSONRPC2Response response = handler.process(request, requestCtx);
|
||
|
|
||
|
if (reportProcTime) {
|
||
|
|
||
|
final long procTimeNanosec = System.nanoTime() - startNanosec;
|
||
|
|
||
|
response.appendNonStdAttribute("xProcTime", procTimeNanosec / 1000 + " us");
|
||
|
}
|
||
|
|
||
|
return response;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @deprecated
|
||
|
*/
|
||
|
public void dispatch(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
|
||
|
|
||
|
process(notification, notificationCtx);
|
||
|
}
|
||
|
|
||
|
|
||
|
@Override
|
||
|
public void process(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
|
||
|
|
||
|
final String method = notification.getMethod();
|
||
|
|
||
|
NotificationHandler handler = getNotificationHandler(method);
|
||
|
|
||
|
if (handler == null) {
|
||
|
|
||
|
// We didn't find a handler for the requested RPC
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Process the notification
|
||
|
|
||
|
handler.process(notification, notificationCtx);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Controls reporting of request processing time by appending a
|
||
|
* non-standard "xProcTime" attribute to the JSON-RPC 2.0 response.
|
||
|
* Reporting is disabled by default.
|
||
|
*
|
||
|
* @param enable {@code true} to enable proccessing time reporting,
|
||
|
* {@code false} to disable it.
|
||
|
*/
|
||
|
public void reportProcTime(final boolean enable) {
|
||
|
|
||
|
reportProcTime = enable;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns {@code true} if reporting of request processing time is
|
||
|
* enabled. See the {@link #reportProcTime} description for more
|
||
|
* information.
|
||
|
*
|
||
|
* @return {@code true} if reporting of request processing time is
|
||
|
* enabled, else {@code false}.
|
||
|
*/
|
||
|
public boolean reportsProcTime() {
|
||
|
|
||
|
return reportProcTime;
|
||
|
}
|
||
|
}
|