diff --git a/java/server/src/org/openqa/selenium/remote/server/JsonHttpRemoteConfig.java b/java/server/src/org/openqa/selenium/remote/server/JsonHttpRemoteConfig.java index 7ac40e0ef4a96..03850be2a26da 100644 --- a/java/server/src/org/openqa/selenium/remote/server/JsonHttpRemoteConfig.java +++ b/java/server/src/org/openqa/selenium/remote/server/JsonHttpRemoteConfig.java @@ -127,6 +127,7 @@ import org.openqa.selenium.remote.server.renderer.JsonErrorExceptionResult; import org.openqa.selenium.remote.server.renderer.JsonResult; import org.openqa.selenium.remote.server.renderer.RedirectResult; +import org.openqa.selenium.remote.server.rest.Renderer; import org.openqa.selenium.remote.server.rest.RestishHandler; import org.openqa.selenium.remote.server.rest.Result; import org.openqa.selenium.remote.server.rest.ResultConfig; @@ -151,23 +152,17 @@ public JsonHttpRemoteConfig(DriverSessions sessions, Logger log) { setUpMappings(sessions, log); } - public void addGlobalHandler(ResultType type, Result result) { - getMapper.addGlobalHandler(type, result); - postMapper.addGlobalHandler(type, result); - deleteMapper.addGlobalHandler(type, result); + public void addNewGetMapping(String path, Class implementationClass) { + getMapper.bind(path, implementationClass); } - public ResultConfig addNewGetMapping(String path, Class implementationClass) { - return getMapper.bind(path, implementationClass); + public void addNewPostMapping(String path, Class implementationClass) { + postMapper.bind(path, implementationClass); } - public ResultConfig addNewPostMapping(String path, Class implementationClass) { - return postMapper.bind(path, implementationClass); - } - - public ResultConfig addNewDeleteMapping(String path, - Class implementationClass) { - return deleteMapper.bind(path, implementationClass); + public void addNewDeleteMapping( + String path, Class implementationClass) { + deleteMapper.bind(path, implementationClass); } public void handleRequest(HttpRequest request, HttpResponse response) @@ -209,261 +204,149 @@ private UrlMapper getUrlMapper(String method) { } private void setUpMappings(DriverSessions driverSessions, Logger logger) { - final EmptyResult emptyResponse = new EmptyResult(); - final JsonResult jsonResponse = new JsonResult(RESPONSE); + Renderer successRenderer = new JsonResult(RESPONSE); + Renderer errorRenderer = new JsonErrorExceptionResult(EXCEPTION, RESPONSE); - getMapper = new UrlMapper(driverSessions, logger); - postMapper = new UrlMapper(driverSessions, logger); - deleteMapper = new UrlMapper(driverSessions, logger); + getMapper = new UrlMapper(driverSessions, logger, successRenderer, errorRenderer); + postMapper = new UrlMapper(driverSessions, logger, successRenderer, errorRenderer); + deleteMapper = new UrlMapper(driverSessions, logger, successRenderer, errorRenderer); - Result jsonErrorResult = new Result(MimeType.EMPTY, - new JsonErrorExceptionResult(EXCEPTION, RESPONSE)); - addGlobalHandler(ResultType.ERROR, jsonErrorResult); + postMapper.bind("/config/drivers", AddConfig.class); - Result xdrpcResult = new Result(MimeType.CROSS_DOMAIN_RPC, - new CrossDomainRpcRenderer(RESPONSE, EXCEPTION), true); - for (ResultType resultType : EnumSet.allOf(ResultType.class)) { - addGlobalHandler(resultType, xdrpcResult); - } + getMapper.bind("/status", Status.class); + + getMapper.bind("/sessions", GetAllSessions.class); + + postMapper.bind("/session", NewSession.class); + getMapper.bind("/session/:sessionId", GetSessionCapabilities.class); + + deleteMapper.bind("/session/:sessionId", DeleteSession.class); + + getMapper.bind("/session/:sessionId/window_handle", GetCurrentWindowHandle.class); + getMapper.bind("/session/:sessionId/window_handles", GetAllWindowHandles.class); + + postMapper.bind("/session/:sessionId/dismiss_alert", DismissAlert.class); + postMapper.bind("/session/:sessionId/accept_alert", AcceptAlert.class); + getMapper.bind("/session/:sessionId/alert_text", GetAlertText.class); + postMapper.bind("/session/:sessionId/alert_text", SetAlertText.class); + + postMapper.bind("/session/:sessionId/url", ChangeUrl.class); + getMapper.bind("/session/:sessionId/url", GetCurrentUrl.class); + + postMapper.bind("/session/:sessionId/forward", GoForward.class); + postMapper.bind("/session/:sessionId/back", GoBack.class); + postMapper.bind("/session/:sessionId/refresh", RefreshPage.class); + + postMapper.bind("/session/:sessionId/execute", ExecuteScript.class); + postMapper.bind("/session/:sessionId/execute_async", ExecuteAsyncScript.class); + + getMapper.bind("/session/:sessionId/source", GetPageSource.class); + + getMapper.bind("/session/:sessionId/screenshot", CaptureScreenshot.class); + + getMapper.bind("/session/:sessionId/title", GetTitle.class); + + postMapper.bind("/session/:sessionId/element", FindElement.class); + getMapper.bind("/session/:sessionId/element/:id", DescribeElement.class); + + postMapper.bind("/session/:sessionId/elements", FindElements.class); + postMapper.bind("/session/:sessionId/element/active", FindActiveElement.class); + + postMapper.bind("/session/:sessionId/element/:id/element", FindChildElement.class); + postMapper.bind("/session/:sessionId/element/:id/elements", FindChildElements.class); + + + postMapper.bind("/session/:sessionId/element/:id/click", ClickElement.class); + getMapper.bind("/session/:sessionId/element/:id/text", GetElementText.class); + postMapper.bind("/session/:sessionId/element/:id/submit", SubmitElement.class); + + postMapper.bind("/session/:sessionId/file", UploadFile.class); + postMapper.bind("/session/:sessionId/element/:id/value", SendKeys.class); + getMapper.bind("/session/:sessionId/element/:id/value", GetElementValue.class); + getMapper.bind("/session/:sessionId/element/:id/name", GetTagName.class); - postMapper.bind("/config/drivers", AddConfig.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/status", Status.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/sessions", GetAllSessions.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session", NewSession.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId", GetSessionCapabilities.class) - .on(ResultType.SUCCESS, new ForwardResult("/WEB-INF/views/sessionCapabilities.jsp")) - .on(ResultType.SUCCESS, jsonResponse, "application/json"); - - deleteMapper.bind("/session/:sessionId", DeleteSession.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/session/:sessionId/window_handle", GetCurrentWindowHandle.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/window_handles", GetAllWindowHandles.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/dismiss_alert", DismissAlert.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/accept_alert", AcceptAlert.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/alert_text", GetAlertText.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/alert_text", SetAlertText.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/url", ChangeUrl.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/url", GetCurrentUrl.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/forward", GoForward.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/back", GoBack.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/refresh", RefreshPage.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/execute", ExecuteScript.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/execute_async", ExecuteAsyncScript.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/source", GetPageSource.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/screenshot", CaptureScreenshot.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/title", GetTitle.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/element", FindElement.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id", DescribeElement.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/elements", FindElements.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/element/active", FindActiveElement.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/element/:id/element", FindChildElement.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/element/:id/elements", FindChildElements.class) - .on(ResultType.SUCCESS, jsonResponse); - - - postMapper.bind("/session/:sessionId/element/:id/click", ClickElement.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/element/:id/text", GetElementText.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/element/:id/submit", SubmitElement.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/file", UploadFile.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/element/:id/value", SendKeys.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/element/:id/value", GetElementValue.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/name", GetTagName.class) - .on(ResultType.SUCCESS, jsonResponse); - - postMapper.bind("/session/:sessionId/element/:id/clear", ClearElement.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/element/:id/selected", GetElementSelected.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/enabled", GetElementEnabled.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/displayed", GetElementDisplayed.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/location", GetElementLocation.class) - .on(ResultType.SUCCESS, jsonResponse); + postMapper.bind("/session/:sessionId/element/:id/clear", ClearElement.class); + getMapper.bind("/session/:sessionId/element/:id/selected", GetElementSelected.class); + getMapper.bind("/session/:sessionId/element/:id/enabled", GetElementEnabled.class); + getMapper.bind("/session/:sessionId/element/:id/displayed", GetElementDisplayed.class); + getMapper.bind("/session/:sessionId/element/:id/location", GetElementLocation.class); getMapper.bind("/session/:sessionId/element/:id/location_in_view", - GetElementLocationInView.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/size", GetElementSize.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/css/:propertyName", GetCssProperty.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/element/:id/attribute/:name", GetElementAttribute.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/element/:id/equals/:other", ElementEquality.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/cookie", GetAllCookies.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/cookie", AddCookie.class) - .on(ResultType.SUCCESS, emptyResponse); - deleteMapper.bind("/session/:sessionId/cookie", DeleteCookie.class) - .on(ResultType.SUCCESS, emptyResponse); - deleteMapper.bind("/session/:sessionId/cookie/:name", DeleteNamedCookie.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/frame", SwitchToFrame.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/frame/parent", SwitchToParentFrame.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/window", SwitchToWindow.class) - .on(ResultType.SUCCESS, emptyResponse); - deleteMapper.bind("/session/:sessionId/window", CloseWindow.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/session/:sessionId/window/:windowHandle/size", GetWindowSize.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/window/:windowHandle/size", SetWindowSize.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/window/:windowHandle/position", GetWindowPosition.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/window/:windowHandle/position", SetWindowPosition.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/window/:windowHandle/maximize", MaximizeWindow.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/timeouts", ConfigureTimeout.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/timeouts/implicit_wait", ImplicitlyWait.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/timeouts/async_script", SetScriptTimeout.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/execute_sql", ExecuteSQL.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/location", GetLocationContext.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/location", SetLocationContext.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/session/:sessionId/application_cache/status", GetAppCacheStatus.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/local_storage/key/:key", GetLocalStorageItem.class) - .on(ResultType.SUCCESS, jsonResponse); - deleteMapper.bind("/session/:sessionId/local_storage/key/:key", RemoveLocalStorageItem.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/local_storage", GetLocalStorageKeys.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/local_storage", SetLocalStorageItem.class) - .on(ResultType.SUCCESS, emptyResponse); - deleteMapper.bind("/session/:sessionId/local_storage", ClearLocalStorage.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/local_storage/size", GetLocalStorageSize.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/session_storage/key/:key", GetSessionStorageItem.class) - .on(ResultType.SUCCESS, jsonResponse); - deleteMapper.bind("/session/:sessionId/session_storage/key/:key", RemoveSessionStorageItem.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/session_storage", GetSessionStorageKeys.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/session_storage", SetSessionStorageItem.class) - .on(ResultType.SUCCESS, emptyResponse); - deleteMapper.bind("/session/:sessionId/session_storage", ClearSessionStorage.class) - .on(ResultType.SUCCESS, emptyResponse); - getMapper.bind("/session/:sessionId/session_storage/size", GetSessionStorageSize.class) - .on(ResultType.SUCCESS, jsonResponse); - - getMapper.bind("/session/:sessionId/orientation", GetScreenOrientation.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/orientation", Rotate.class) - .on(ResultType.SUCCESS, emptyResponse); - - postMapper.bind("/session/:sessionId/moveto", MouseMoveToLocation.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/click", ClickInSession.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/doubleclick", DoubleClickInSession.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/buttondown", MouseDown.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/buttonup", MouseUp.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/keys", SendKeyToActiveElement.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/session/:sessionId/ime/available_engines", ImeGetAvailableEngines.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/ime/active_engine", ImeGetActiveEngine.class) - .on(ResultType.SUCCESS, jsonResponse); - getMapper.bind("/session/:sessionId/ime/activated", ImeIsActivated.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/ime/deactivate", ImeDeactivate.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/ime/activate", ImeActivateEngine.class) - .on(ResultType.SUCCESS, jsonResponse); + GetElementLocationInView.class); + getMapper.bind("/session/:sessionId/element/:id/size", GetElementSize.class); + getMapper.bind("/session/:sessionId/element/:id/css/:propertyName", GetCssProperty.class); + + getMapper.bind("/session/:sessionId/element/:id/attribute/:name", GetElementAttribute.class); + getMapper.bind("/session/:sessionId/element/:id/equals/:other", ElementEquality.class); + + getMapper.bind("/session/:sessionId/cookie", GetAllCookies.class); + postMapper.bind("/session/:sessionId/cookie", AddCookie.class); + deleteMapper.bind("/session/:sessionId/cookie", DeleteCookie.class); + deleteMapper.bind("/session/:sessionId/cookie/:name", DeleteNamedCookie.class); + + postMapper.bind("/session/:sessionId/frame", SwitchToFrame.class); + postMapper.bind("/session/:sessionId/frame/parent", SwitchToParentFrame.class); + postMapper.bind("/session/:sessionId/window", SwitchToWindow.class); + deleteMapper.bind("/session/:sessionId/window", CloseWindow.class); + + getMapper.bind("/session/:sessionId/window/:windowHandle/size", GetWindowSize.class); + postMapper.bind("/session/:sessionId/window/:windowHandle/size", SetWindowSize.class); + getMapper.bind("/session/:sessionId/window/:windowHandle/position", GetWindowPosition.class); + postMapper.bind("/session/:sessionId/window/:windowHandle/position", SetWindowPosition.class); + postMapper.bind("/session/:sessionId/window/:windowHandle/maximize", MaximizeWindow.class); + + postMapper.bind("/session/:sessionId/timeouts", ConfigureTimeout.class); + postMapper.bind("/session/:sessionId/timeouts/implicit_wait", ImplicitlyWait.class); + postMapper.bind("/session/:sessionId/timeouts/async_script", SetScriptTimeout.class); + + postMapper.bind("/session/:sessionId/execute_sql", ExecuteSQL.class); + + getMapper.bind("/session/:sessionId/location", GetLocationContext.class); + postMapper.bind("/session/:sessionId/location", SetLocationContext.class); + + getMapper.bind("/session/:sessionId/application_cache/status", GetAppCacheStatus.class); + + getMapper.bind("/session/:sessionId/local_storage/key/:key", GetLocalStorageItem.class); + deleteMapper.bind("/session/:sessionId/local_storage/key/:key", RemoveLocalStorageItem.class); + getMapper.bind("/session/:sessionId/local_storage", GetLocalStorageKeys.class); + postMapper.bind("/session/:sessionId/local_storage", SetLocalStorageItem.class); + deleteMapper.bind("/session/:sessionId/local_storage", ClearLocalStorage.class); + getMapper.bind("/session/:sessionId/local_storage/size", GetLocalStorageSize.class); + + getMapper.bind("/session/:sessionId/session_storage/key/:key", GetSessionStorageItem.class); + deleteMapper.bind("/session/:sessionId/session_storage/key/:key", RemoveSessionStorageItem.class); + getMapper.bind("/session/:sessionId/session_storage", GetSessionStorageKeys.class); + postMapper.bind("/session/:sessionId/session_storage", SetSessionStorageItem.class); + deleteMapper.bind("/session/:sessionId/session_storage", ClearSessionStorage.class); + getMapper.bind("/session/:sessionId/session_storage/size", GetSessionStorageSize.class); + + getMapper.bind("/session/:sessionId/orientation", GetScreenOrientation.class); + postMapper.bind("/session/:sessionId/orientation", Rotate.class); + + postMapper.bind("/session/:sessionId/moveto", MouseMoveToLocation.class); + postMapper.bind("/session/:sessionId/click", ClickInSession.class); + postMapper.bind("/session/:sessionId/doubleclick", DoubleClickInSession.class); + postMapper.bind("/session/:sessionId/buttondown", MouseDown.class); + postMapper.bind("/session/:sessionId/buttonup", MouseUp.class); + postMapper.bind("/session/:sessionId/keys", SendKeyToActiveElement.class); + + getMapper.bind("/session/:sessionId/ime/available_engines", ImeGetAvailableEngines.class); + getMapper.bind("/session/:sessionId/ime/active_engine", ImeGetActiveEngine.class); + getMapper.bind("/session/:sessionId/ime/activated", ImeIsActivated.class); + postMapper.bind("/session/:sessionId/ime/deactivate", ImeDeactivate.class); + postMapper.bind("/session/:sessionId/ime/activate", ImeActivateEngine.class); // Advanced Touch API - postMapper.bind("/session/:sessionId/touch/click", SingleTapOnElement.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/down", Down.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/up", Up.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/move", Move.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/scroll", Scroll.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/doubleclick", DoubleTapOnElement.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/longclick", LongPressOnElement.class) - .on(ResultType.SUCCESS, emptyResponse); - postMapper.bind("/session/:sessionId/touch/flick", Flick.class) - .on(ResultType.SUCCESS, emptyResponse); - - getMapper.bind("/session/:sessionId/log/types", GetAvailableLogTypesHandler.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/session/:sessionId/log", GetLogHandler.class) - .on(ResultType.SUCCESS, jsonResponse); - postMapper.bind("/logs", GetSessionLogsHandler.class) - .on(ResultType.SUCCESS, jsonResponse); + postMapper.bind("/session/:sessionId/touch/click", SingleTapOnElement.class); + postMapper.bind("/session/:sessionId/touch/down", Down.class); + postMapper.bind("/session/:sessionId/touch/up", Up.class); + postMapper.bind("/session/:sessionId/touch/move", Move.class); + postMapper.bind("/session/:sessionId/touch/scroll", Scroll.class); + postMapper.bind("/session/:sessionId/touch/doubleclick", DoubleTapOnElement.class); + postMapper.bind("/session/:sessionId/touch/longclick", LongPressOnElement.class); + postMapper.bind("/session/:sessionId/touch/flick", Flick.class); + + getMapper.bind("/session/:sessionId/log/types", GetAvailableLogTypesHandler.class); + postMapper.bind("/session/:sessionId/log", GetLogHandler.class); + postMapper.bind("/logs", GetSessionLogsHandler.class); } } diff --git a/java/server/src/org/openqa/selenium/remote/server/renderer/JsonResult.java b/java/server/src/org/openqa/selenium/remote/server/renderer/JsonResult.java index c4646df0aa77e..ec4f25aa8ca0b 100644 --- a/java/server/src/org/openqa/selenium/remote/server/renderer/JsonResult.java +++ b/java/server/src/org/openqa/selenium/remote/server/renderer/JsonResult.java @@ -16,9 +16,14 @@ package org.openqa.selenium.remote.server.renderer; +import static com.google.common.base.Strings.nullToEmpty; +import static org.openqa.selenium.remote.HttpSessionId.getSessionId; + import com.google.common.base.Charsets; import org.openqa.selenium.remote.BeanToJsonConverter; +import org.openqa.selenium.remote.ErrorCodes; +import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.server.HttpRequest; import org.openqa.selenium.remote.server.HttpResponse; import org.openqa.selenium.remote.server.rest.Renderer; @@ -41,6 +46,9 @@ public JsonResult(String propertyName) { public void render(HttpRequest request, HttpResponse response, RestishHandler handler) throws Exception { Object result = request.getAttribute(propertyName); + if (result == null) { + result = prepareDefaultResponse(request); + } String json = new BeanToJsonConverter().convert(result); ByteBuffer bb = Charsets.UTF_8.encode(json); @@ -52,4 +60,13 @@ public void render(HttpRequest request, HttpResponse response, RestishHandler ha response.setContent(data); response.end(); } + + private Response prepareDefaultResponse(HttpRequest request) { + Response response = new Response(); + response.setStatus(ErrorCodes.SUCCESS); + response.setState(ErrorCodes.SUCCESS_STRING); + response.setSessionId(nullToEmpty(getSessionId(request.getUri()))); + response.setValue(null); + return response; + } } diff --git a/java/server/src/org/openqa/selenium/remote/server/rest/ResultConfig.java b/java/server/src/org/openqa/selenium/remote/server/rest/ResultConfig.java index 6f6eac05b85bd..b5821327cf7f3 100644 --- a/java/server/src/org/openqa/selenium/remote/server/rest/ResultConfig.java +++ b/java/server/src/org/openqa/selenium/remote/server/rest/ResultConfig.java @@ -16,12 +16,7 @@ package org.openqa.selenium.remote.server.rest; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.ErrorCodes; @@ -46,7 +41,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; -import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -56,24 +50,30 @@ public class ResultConfig { + private final Renderer successRenderer; + private final Renderer errorRenderer; + private final String[] sections; private final HandlerFactory handlerFactory; private final DriverSessions sessions; - private final Multimap resultToRender = LinkedHashMultimap.create(); private final String url; private final Logger log; - public ResultConfig(String url, Class handlerClazz, DriverSessions sessions, - Logger log) { - this.url = url; - this.log = log; + public ResultConfig( + String url, Class handlerClazz, + DriverSessions sessions, Logger log, + Renderer successRenderer, Renderer errorRenderer) { if (url == null || handlerClazz == null) { throw new IllegalArgumentException("You must specify the handler and the url"); } - sections = url.split("/"); + this.url = url; + this.log = log; + this.sections = url.split("/"); this.sessions = sessions; this.handlerFactory = getHandlerFactory(handlerClazz); + this.successRenderer = successRenderer; + this.errorRenderer = errorRenderer; } @@ -130,50 +130,6 @@ protected RestishHandler populate(RestishHandler handler, String pathString) { return handler; } - /** - * Configures this instance to handle a particular type of result with the given renderer. This - * result handler will be registered with an empty mime-type. Accordingly, it will only be used - * if there are no other handlers registered with an exact mime-type match. - * - * @param resultType The type of result to configure. - * @param renderer The renderer to use. - * @return A self reference for fluency. - * @see #on(ResultType, Result) - */ - public ResultConfig on(ResultType resultType, Renderer renderer) { - return on(resultType, renderer, ""); - } - - /* - * Configure this ResultConfig to handle results of type ResultType with a specific renderer. The - * mimeType is used to distinguish between JSON calls and "ordinary" browser pointed at the remote - * WD Server, which is not implemented at all yet. - * @see #on(ResultType, Result) - */ - public ResultConfig on(ResultType success, Renderer renderer, String mimeType) { - return on(success, new Result(mimeType, renderer)); - } - - /** - * Configures how this instance will handle specific types of results. Each ResultType may be - * handled by multiple Results. Upon rendering a response, this instance will select the first - * Result that is an exact mime-type match for the original HTTP request (results are checked in - * the order registered). There may only be one Result registered for each mime-type. - * - * @param type The type of result to configure for. - * @param result The handler for the given result type. - * @return A self reference for fluency. - */ - public ResultConfig on(ResultType type, Result result) { - // There should not be more than one renderer for each result and - // mime type. - for (Result existingResult : resultToRender.get(type)) { - assert(!existingResult.isExactMimeTypeMatch(result.getMimeType())); - } - resultToRender.put(type, result); - return this; - } - public void handle(String pathInfo, final HttpRequest request, final HttpResponse response) throws Exception { String sessionId = HttpSessionId.getSessionId(request.getUri()); @@ -185,7 +141,6 @@ public void handle(String pathInfo, final HttpRequest request, final RestishHandler handler = getHandler(pathInfo, sessId); try { - if (handler instanceof JsonParametersAware) { setJsonParameters(request, handler); } @@ -208,7 +163,8 @@ public void handle(String pathInfo, final HttpRequest request, } } catch (UnreachableBrowserException e){ throwUpIfSessionTerminated(sessId); - replyError(request, response, e); + request.setAttribute("exception", e); + errorRenderer.render(request, response, null); return; } catch (SessionNotFoundException e){ throw e; @@ -229,7 +185,7 @@ public void handle(String pathInfo, final HttpRequest request, request.setAttribute("exception", e); } - final Renderer renderer = getRenderer(result, request); + final Renderer renderer = result == ResultType.SUCCESS ? successRenderer : errorRenderer; renderer.render(request, response, handler); response.end(); @@ -243,13 +199,6 @@ public void handle(String pathInfo, final HttpRequest request, } } - private void replyError(HttpRequest request, final HttpResponse response, Exception e) - throws Exception { - Renderer renderer2 = getRenderer(ResultType.ERROR, request); - request.setAttribute("exception", e); - renderer2.render(request, response, null); - } - private void throwUpIfSessionTerminated(SessionId sessId) throws Exception { if (sessId == null) return; Session session = sessions.get(sessId); @@ -259,19 +208,6 @@ private void throwUpIfSessionTerminated(SessionId sessId) throws Exception { } } - @VisibleForTesting - Renderer getRenderer(ResultType resultType, HttpRequest request) { - Collection results = checkNotNull(resultToRender.get(resultType)); - Result tempToUse = null; - for (Result res : results) { - if (tempToUse == null && !res.isOnlyForExactMatch() - || res.isExactMimeTypeMatch(request.getHeader("Accept"))) { - tempToUse = res; - } - } - return checkNotNull(tempToUse).getRenderer(); - } - @SuppressWarnings("unchecked") private void setJsonParameters(HttpRequest request, RestishHandler handler) throws Exception { BufferedReader reader = new BufferedReader(request.getReader()); diff --git a/java/server/src/org/openqa/selenium/remote/server/rest/UrlMapper.java b/java/server/src/org/openqa/selenium/remote/server/rest/UrlMapper.java index 707bf05ec9aa0..4fa1c98d31b8b 100644 --- a/java/server/src/org/openqa/selenium/remote/server/rest/UrlMapper.java +++ b/java/server/src/org/openqa/selenium/remote/server/rest/UrlMapper.java @@ -16,44 +16,37 @@ package org.openqa.selenium.remote.server.rest; -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; - import org.openqa.selenium.remote.server.DriverSessions; -import java.util.Collection; import java.util.LinkedHashSet; -import java.util.Map; import java.util.Set; import java.util.logging.Logger; public class UrlMapper { - private final Multimap globals = LinkedHashMultimap.create(); private final Set configs = new LinkedHashSet(); private final DriverSessions sessions; private final Logger log; + private final Renderer successRenderer; + private final Renderer errorRenderer; - public UrlMapper(DriverSessions sessions, Logger log) { + public UrlMapper(DriverSessions sessions, Logger log, + Renderer successRenderer, Renderer errorRenderer) { this.sessions = sessions; this.log = log; + this.successRenderer = successRenderer; + this.errorRenderer = errorRenderer; } - public ResultConfig bind(String url, Class handlerClazz) { + public void bind(String url, Class handlerClazz) { ResultConfig existingConfig = getConfig(url); if (existingConfig != null) { configs.remove(existingConfig); } - ResultConfig config = new ResultConfig(url, handlerClazz, sessions, log); + ResultConfig config = new ResultConfig( + url, handlerClazz, sessions, log, successRenderer, errorRenderer); configs.add(config); - Map> map = globals.asMap(); - for (Map.Entry> entry : map.entrySet()) { - for (Result result : entry.getValue()) { - config.on(entry.getKey(), result); - } - } - return config; } public ResultConfig getConfig(String url) { @@ -65,12 +58,4 @@ public ResultConfig getConfig(String url) { return null; } - - public void addGlobalHandler(ResultType type, Result result) { - globals.put(type, result); - - for (ResultConfig config : configs) { - config.on(type, result); - } - } } diff --git a/java/server/test/org/openqa/selenium/remote/server/rest/ResultConfigTest.java b/java/server/test/org/openqa/selenium/remote/server/rest/ResultConfigTest.java index 7e783ac0d6edd..82561c1b7df96 100644 --- a/java/server/test/org/openqa/selenium/remote/server/rest/ResultConfigTest.java +++ b/java/server/test/org/openqa/selenium/remote/server/rest/ResultConfigTest.java @@ -23,15 +23,14 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import org.junit.Test; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.SessionId; -import org.openqa.selenium.remote.server.HttpRequest; import org.openqa.selenium.remote.server.StubHandler; +import org.openqa.selenium.remote.server.renderer.JsonErrorExceptionResult; +import org.openqa.selenium.remote.server.renderer.JsonResult; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.UndeclaredThrowableException; @@ -41,10 +40,14 @@ public class ResultConfigTest { private Logger logger = Logger.getLogger(ResultConfigTest.class.getName()); private static final SessionId dummySessionId = new SessionId("Test"); + private static final JsonResult successRenderer = new JsonResult("result"); + private static final JsonErrorExceptionResult errorRenderer = new JsonErrorExceptionResult( + "exception", "result"); @Test public void testShouldMatchBasicUrls() throws Exception { - ResultConfig config = new ResultConfig("/fish", StubHandler.class, null, logger); + ResultConfig config = new ResultConfig( + "/fish", StubHandler.class, null, logger, successRenderer, errorRenderer); assertThat(config.getHandler("/fish", dummySessionId), is(notNullValue())); assertThat(config.getHandler("/cod", dummySessionId), is(nullValue())); @@ -53,7 +56,7 @@ public void testShouldMatchBasicUrls() throws Exception { @Test public void testShouldNotAllowNullToBeUsedAsTheUrl() { try { - new ResultConfig(null, StubHandler.class, null, logger); + new ResultConfig(null, StubHandler.class, null, logger, successRenderer, errorRenderer); fail("Should have failed"); } catch (IllegalArgumentException e) { exceptionWasExpected(); @@ -63,7 +66,7 @@ public void testShouldNotAllowNullToBeUsedAsTheUrl() { @Test public void testShouldNotAllowNullToBeUsedForTheHandler() { try { - new ResultConfig("/cheese", null, null, logger); + new ResultConfig("/cheese", null, null, logger, successRenderer, errorRenderer); fail("Should have failed"); } catch (IllegalArgumentException e) { exceptionWasExpected(); @@ -72,7 +75,8 @@ public void testShouldNotAllowNullToBeUsedForTheHandler() { @Test public void testShouldMatchNamedParameters() throws Exception { - ResultConfig config = new ResultConfig("/foo/:bar", NamedParameterHandler.class, null, logger); + ResultConfig config = new ResultConfig("/foo/:bar", NamedParameterHandler.class, null, logger, + successRenderer, errorRenderer); RestishHandler handler = config.getHandler("/foo/fishy", dummySessionId); assertThat(handler, is(notNullValue())); @@ -80,7 +84,8 @@ public void testShouldMatchNamedParameters() throws Exception { @Test public void testShouldSetNamedParametersOnHandler() throws Exception { - ResultConfig config = new ResultConfig("/foo/:bar", NamedParameterHandler.class, null, logger); + ResultConfig config = new ResultConfig("/foo/:bar", NamedParameterHandler.class, null, logger, + successRenderer, errorRenderer); NamedParameterHandler handler = (NamedParameterHandler) config.getHandler("/foo/fishy", dummySessionId); @@ -90,7 +95,8 @@ public void testShouldSetNamedParametersOnHandler() throws Exception { @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"}) @Test public void testShouldGracefullyHandleNullInputs() { - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger); + ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger, + successRenderer, errorRenderer); assertNull(config.getRootExceptionCause(null)); } @@ -105,7 +111,8 @@ public void testCanPeelNestedExceptions() { ExecutionException execution = new ExecutionException("General WebDriver error", webdriverException); - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger); + ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger, + successRenderer, errorRenderer); Throwable toClient = config.getRootExceptionCause(execution); assertEquals(toClient, runtime); } @@ -118,83 +125,12 @@ public void testDoesNotPeelTooManyLayersFromNestedExceptions() { InvocationTargetException invocation = new InvocationTargetException(noElement); UndeclaredThrowableException undeclared = new UndeclaredThrowableException(invocation); - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger); + ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger, + successRenderer, errorRenderer); Throwable toClient = config.getRootExceptionCause(undeclared); assertEquals(noElement, toClient); } - @Test - public void testFailsWhenUnableToDetermineResultTypeForRequest_noHandlersRegistered() { - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger); - final HttpRequest mockRequest = mock(HttpRequest.class); - - try { - config.getRenderer(ResultType.ERROR, mockRequest); - fail("Should have thrown a NPE"); - } catch (NullPointerException expected) { - } - } - - @Test - public void testSelectsFirstAvailableRendererWhenThereAreNoMimeTypeMatches() { - Renderer mockRenderer1 = mock(Renderer.class, "renderer1"); - Renderer mockRenderer2 = mock(Renderer.class, "renderer2"); - final HttpRequest mockRequest = mock(HttpRequest.class); - - when(mockRequest.getHeader("Accept")).thenReturn("application/json"); - - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger) - .on(ResultType.SUCCESS, mockRenderer1, "text/plain") - .on(ResultType.SUCCESS, mockRenderer2, "text/html"); - - assertEquals(mockRenderer1, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - - @Test - public void testSelectsRenderWithMimeTypeMatch() { - Renderer mockRenderer1 = mock(Renderer.class, "renderer1"); - Renderer mockRenderer2 = mock(Renderer.class, "renderer2"); - final HttpRequest mockRequest = mock(HttpRequest.class); - - when(mockRequest.getHeader("Accept")).thenReturn("application/json"); - - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger) - .on(ResultType.SUCCESS, mockRenderer1) - .on(ResultType.SUCCESS, mockRenderer2, "application/json"); - - assertEquals(mockRenderer2, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - - @Test - public void testUsesFirstRegisteredRendererWhenNoMimeTypeMatches() { - Renderer mockRenderer1 = mock(Renderer.class, "renderer1"); - Renderer mockRenderer2 = mock(Renderer.class, "renderer2"); - final HttpRequest mockRequest = mock(HttpRequest.class); - - when(mockRequest.getHeader("Accept")).thenReturn("application/json"); - - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger) - .on(ResultType.SUCCESS, mockRenderer1, "text/html") - .on(ResultType.SUCCESS, mockRenderer2); - - assertEquals(mockRenderer1, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - - @Test - public void testSkipsRenderersThatRequireASpecificTypeOfMimeType() { - Renderer mockRenderer1 = mock(Renderer.class, "renderer1"); - Renderer mockRenderer2 = mock(Renderer.class, "renderer2"); - final HttpRequest mockRequest = mock(HttpRequest.class); - - when(mockRequest.getHeader("Accept")).thenReturn("application/json"); - - ResultConfig config = new ResultConfig("/foo/:bar", StubHandler.class, null, logger) - .on(ResultType.SUCCESS, new Result("text/html", mockRenderer1, true)) - .on(ResultType.SUCCESS, mockRenderer2); - - assertEquals(mockRenderer2, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - private void exceptionWasExpected() { } diff --git a/java/server/test/org/openqa/selenium/remote/server/rest/UrlMapperTest.java b/java/server/test/org/openqa/selenium/remote/server/rest/UrlMapperTest.java index 1c3937a54f489..d3d8b8f6d0d36 100644 --- a/java/server/test/org/openqa/selenium/remote/server/rest/UrlMapperTest.java +++ b/java/server/test/org/openqa/selenium/remote/server/rest/UrlMapperTest.java @@ -31,6 +31,7 @@ import org.openqa.selenium.remote.server.HttpRequest; import org.openqa.selenium.remote.server.HttpResponse; import org.openqa.selenium.remote.server.StubHandler; +import org.openqa.selenium.remote.server.renderer.JsonResult; import java.util.logging.Logger; @@ -41,7 +42,8 @@ public class UrlMapperTest { @Before public void setUp() { - mapper = new UrlMapper(new DefaultDriverSessions(), log); + JsonResult renderer = new JsonResult("success"); + mapper = new UrlMapper(new DefaultDriverSessions(), log, renderer, renderer); } @Test @@ -63,49 +65,6 @@ public void testShouldInjectDependenciesViaTheConstructor() throws Exception { assertThat(handler.getSessions(), is(notNullValue())); } - @Test - public void testAppliesGlobalHandlersToNewConfigs() { - Renderer renderer = new StubRenderer(); - Result result = new Result("", renderer); - HttpRequest mockRequest = mock(HttpRequest.class); - - mapper.addGlobalHandler(ResultType.SUCCESS, result); - mapper.bind("/example", SessionHandler.class); - - ResultConfig config = mapper.getConfig("/example"); - assertEquals(renderer, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - - @Test - public void testAppliesNewGlobalHandlersToExistingConfigs() { - Renderer renderer = new StubRenderer(); - Result result = new Result("", renderer); - HttpRequest mockRequest = mock(HttpRequest.class); - - mapper.bind("/example", SessionHandler.class); - mapper.addGlobalHandler(ResultType.SUCCESS, result); - - ResultConfig config = mapper.getConfig("/example"); - assertEquals(renderer, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - - @Test - public void testPermitsMultipleGlobalHandlersWithDifferentMimeTypes() { - Renderer renderer = new StubRenderer(); - - final HttpRequest mockRequest = mock(HttpRequest.class); - - when(mockRequest.getHeader("Accept")).thenReturn("application/json"); - - mapper.addGlobalHandler(ResultType.SUCCESS, new Result("", new StubRenderer())); - mapper.addGlobalHandler(ResultType.SUCCESS, new Result("application/json", renderer )); - mapper.bind("/example", SessionHandler.class) - .on(ResultType.SUCCESS, new Result("text/plain", new StubRenderer())); - - ResultConfig config = mapper.getConfig("/example"); - assertEquals(renderer, config.getRenderer(ResultType.SUCCESS, mockRequest)); - } - public static class SessionHandler implements RestishHandler { private final DriverSessions sessions; @@ -122,9 +81,4 @@ public ResultType handle() { return ResultType.SUCCESS; } } - - private static class StubRenderer implements Renderer { - public void render(HttpRequest request, HttpResponse response, RestishHandler handler) throws Exception { - } - } }