package org.webcat.core.webapi; import org.apache.http.HttpStatus; import org.webcat.core.EOBase; import org.webcat.core.EntityRequestInfo; import org.webcat.core.User; import org.webcat.core.http.BasicAuthenticationFilter; import org.webcat.core.http.MetaRequestHandler; import org.webcat.core.http.NoCacheRequestFilter; import org.webcat.core.http.RequestHandlerBinder; import org.webcat.core.http.RequestHandlerWithResponse; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation._NSUtilities; //------------------------------------------------------------------------- /** * The request handler for the Web-CAT external web API. * * @author Tony Allevato * @author Last changed by $Author: aallowat $ * @version $Revision: 1.1 $, $Date: 2012/06/22 16:23:17 $ */ public class WebAPIRequestHandler extends MetaRequestHandler { //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Initializes a new {@code WebAPIRequestHandler}. */ public WebAPIRequestHandler() { controllerCache = new NSMutableDictionary<String, WebAPIController>(); serveRegex("(.+" + FORMAT_NEG + "(?:/.+" + FORMAT_NEG + "(?:/.+" + FORMAT_NEG + ")?)?)" + FORMAT_CAPTURE + "$").with(new WebAPIDispatcher()); } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Overrides the {@link MetaRequestHandler#register(RequestHandlerBinder)} * method to ensure that helper filters are attached to every service * binder. * * @param binder the incoming binder * @return the possibly modified binder */ @Override protected RequestHandlerBinder register(RequestHandlerBinder binder) { return binder.through(new NoCacheRequestFilter()) .through(new ValidUserOnlyAuthenticationFilter()); } // ---------------------------------------------------------- /** * Retrieves the {@link WebAPIController} for the specified entity type, * creating it for the first time if necessary. * * @param entityName the type of entity for which to retrieve the * controller * @return the controller, or null if none was found */ private WebAPIController controllerForType(String entityName) { WebAPIController controller = controllerCache.objectForKey(entityName); if (controller == null) { try { Class<?> klass = _NSUtilities.classWithName( entityName + CONTROLLER_SUFFIX); controller = (WebAPIController) klass.newInstance(); controllerCache.setObjectForKey(controller, entityName); } catch (Exception e) { return null; } } return controller; } //~ Inner classes ......................................................... // ---------------------------------------------------------- /** * This authentication filter only verifies that the user is a valid user * (that is, it always returns true). It is up to the individual actions to * determine whether the action should be allowed based on the access * privileges of the user making the request, and to filter the response * based on that user. */ private class ValidUserOnlyAuthenticationFilter extends BasicAuthenticationFilter { // ---------------------------------------------------------- @Override protected String realmForContext(WOContext context) { return "Web-CAT Web API"; } // ---------------------------------------------------------- @Override protected boolean userHasAccess(User user) { return true; } } // ---------------------------------------------------------- /** * Dispatches the API call to the appropriate controller class and action * method. */ private class WebAPIDispatcher implements RequestHandlerWithResponse { // ---------------------------------------------------------- public void handleRequest(WORequest request, WOResponse response) throws Exception { String path = request.requestHandlerPath(); EntityRequestInfo info = EntityRequestInfo.fromRequestHandlerPath(path, true); if (info.entityName() != null) { WebAPIController controller = controllerForType(info.entityName()); if (controller != null) { controller.handleRequest(request, response); } else { response.setContent(""); response.setStatus(HttpStatus.SC_FORBIDDEN); } } else { response.setContent(""); response.setStatus(HttpStatus.SC_FORBIDDEN); } } } //~ Static/instance variables ............................................. /** * The request handler key that is used to register the handler. */ public static final String REQUEST_HANDLER_KEY = "api"; private static final String FORMAT_PATTERN = "(?:xml|json)"; private static final String FORMAT_CAPTURE = "(\\." + FORMAT_PATTERN + ")?"; private static final String FORMAT_NEG = "(?<!\\." + FORMAT_PATTERN + ")"; // The index of the capture group that contains the response format (since // Java doesn't support named capture groups until 1.7). We must make sure // that all of the patterns in the methods above are arranged so that this // is always the same. public static final int FORMAT_CAPTURE_GROUP = 2; private static final String CONTROLLER_SUFFIX = "WebAPIController"; private NSMutableDictionary<String, WebAPIController> controllerCache; }