Created
February 20, 2012 17:23
-
-
Save freynaud/1870188 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Eclipse Workspace Patch 1.0 | |
#P selenium | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequestHandler.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequestHandler.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequestHandler.java (working copy) | |
@@ -1,139 +0,0 @@ | |
-/* | |
-Copyright 2011 WebDriver committers | |
-Copyright 2011 Software Freedom Conservancy | |
- | |
-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.openqa.grid.web.servlet.handler; | |
- | |
-import java.io.IOException; | |
-import java.util.HashMap; | |
-import java.util.Iterator; | |
-import java.util.Map; | |
-import java.util.logging.Logger; | |
- | |
-import javax.servlet.http.HttpServletRequest; | |
-import javax.servlet.http.HttpServletResponse; | |
- | |
-import org.json.JSONException; | |
-import org.json.JSONObject; | |
-import org.openqa.grid.internal.ExternalSessionKey; | |
-import org.openqa.grid.common.SeleniumProtocol; | |
-import org.openqa.grid.common.exception.GridException; | |
-import org.openqa.grid.internal.exception.NewSessionException; | |
-import org.openqa.grid.internal.utils.ForwardConfiguration; | |
-import org.openqa.grid.internal.Registry; | |
-import org.openqa.grid.internal.TestSession; | |
-import org.openqa.jetty.jetty.servlet.ServletHttpResponse; | |
- | |
-/** | |
- * Handles an individual request, scope is a single request and hence a single thread. | |
- */ | |
-public class WebDriverRequestHandler extends RequestHandler { | |
- | |
- private static final Logger log = Logger.getLogger(WebDriverRequestHandler.class.getName()); | |
- | |
- protected WebDriverRequestHandler(HttpServletRequest request, HttpServletResponse response, | |
- Registry registry) { | |
- super(request, response, registry); | |
- } | |
- | |
- | |
- @Override | |
- public RequestType extractRequestType() { | |
- | |
- if ("/session".equals(getRequest().getPathInfo())) { | |
- return RequestType.START_SESSION; | |
- } else if (getRequest().getMethod().equalsIgnoreCase("DELETE")) { | |
- ExternalSessionKey | |
- externalKey = ExternalSessionKey.fromWebDriverRequest(getRequest().getPathInfo()); | |
- if (getRequest().getPathInfo().endsWith("/session/" + externalKey.getKey())) { | |
- return RequestType.STOP_SESSION; | |
- } | |
- } | |
- return RequestType.REGULAR; | |
- } | |
- | |
- @Override | |
- public ExternalSessionKey extractSession() { | |
- if (getRequestType() == RequestType.START_SESSION) { | |
- throw new IllegalAccessError("Cannot call that method of a new session request."); | |
- } | |
- String path = getRequest().getPathInfo(); | |
- return ExternalSessionKey.fromWebDriverRequest(path); | |
- } | |
- | |
- // TODO freynaud parsing is so so. | |
- @SuppressWarnings("unchecked") | |
- // JSON iterator. | |
- @Override | |
- public Map<String, Object> extractDesiredCapability() { | |
- String json = getRequestBody(); | |
- Map<String, Object> desiredCapability = new HashMap<String, Object>(); | |
- try { | |
- JSONObject map = new JSONObject(json); | |
- JSONObject dc = map.getJSONObject("desiredCapabilities"); | |
- for (Iterator iterator = dc.keys(); iterator.hasNext();) { | |
- String key = (String) iterator.next(); | |
- Object value = dc.get(key); | |
- if (value == JSONObject.NULL) { | |
- value = null; | |
- } | |
- desiredCapability.put(key, value); | |
- } | |
- } catch (JSONException e) { | |
- throw new GridException("Cannot extract a capabilities from the request " + json); | |
- } | |
- return desiredCapability; | |
- } | |
- | |
- @Override | |
- public ExternalSessionKey forwardNewSessionRequestAndUpdateRegistry(TestSession session) throws NewSessionException{ | |
- try { | |
- // here, don't forward the requestBody directly, but read the | |
- // desiredCapabilities from the session instead. | |
- // That allow the TestSessionListener.before modification of the | |
- // capability map to be propagated. | |
- JSONObject c = new JSONObject(); | |
- c.put("desiredCapabilities", session.getRequestedCapabilities()); | |
- String content = c.toString(); | |
- ForwardConfiguration config = new ForwardConfiguration(); | |
- config.setProtocol(SeleniumProtocol.WebDriver); | |
- config.setNewSessionRequest(true); | |
- config.setContentOverWrite(content); | |
- session.forward(getRequest(), getResponse(), config); | |
- } catch (IOException e) { | |
- //log.warning("Error forwarding the request " + e.getMessage()); | |
- throw new NewSessionException("Error forwarding the request " + e.getMessage(),e); | |
- } catch (JSONException e) { | |
- //log.warning("Error with the request " + e.getMessage()); | |
- throw new NewSessionException("Error with the request " + e.getMessage(),e); | |
- } | |
- | |
- if (getResponse().containsHeader("Location")) { | |
- String location = | |
- ((ServletHttpResponse) getResponse()).getHttpResponse().getField("Location"); | |
- ExternalSessionKey res = ExternalSessionKey.fromWebDriverRequest( location); | |
- if ( res!=null){ | |
- return res; | |
- }else { | |
- throw new NewSessionException("couldn't extract the new session from the response header."); | |
- } | |
- } else { | |
- //log.warning("Error, header should contain Location"); | |
- throw new NewSessionException("Error, header should contain Location "); | |
- } | |
- | |
- } | |
-} | |
Index: java/server/src/org/openqa/grid/internal/NewSessionRequestQueue.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/internal/NewSessionRequestQueue.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/internal/NewSessionRequestQueue.java (working copy) | |
@@ -108,7 +108,7 @@ | |
public synchronized Iterable<DesiredCapabilities> getDesiredCapabilities() { | |
List<DesiredCapabilities> result = new ArrayList<DesiredCapabilities>(); | |
for (RequestHandler req : newSessionRequests) { | |
- result.add(new DesiredCapabilities(req.getDesiredCapabilities())); | |
+ result.add(new DesiredCapabilities(req.getRequest().getDesiredCapabilities())); | |
} | |
return result; | |
} | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/SeleniumBasedRequest.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/SeleniumBasedRequest.java (revision 0) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/SeleniumBasedRequest.java (revision 0) | |
@@ -0,0 +1,187 @@ | |
+package org.openqa.grid.web.servlet.handler; | |
+ | |
+import java.io.BufferedReader; | |
+import java.io.ByteArrayInputStream; | |
+import java.io.IOException; | |
+import java.io.InputStream; | |
+import java.io.InputStreamReader; | |
+import java.nio.ByteBuffer; | |
+import java.nio.CharBuffer; | |
+import java.nio.charset.CharacterCodingException; | |
+import java.nio.charset.Charset; | |
+import java.nio.charset.CharsetDecoder; | |
+import java.nio.charset.CharsetEncoder; | |
+import java.util.Map; | |
+ | |
+import javax.servlet.ServletInputStream; | |
+import javax.servlet.http.HttpServletRequest; | |
+import javax.servlet.http.HttpServletRequestWrapper; | |
+ | |
+import org.apache.commons.io.IOUtils; | |
+import org.openqa.grid.common.SeleniumProtocol; | |
+import org.openqa.grid.internal.ExternalSessionKey; | |
+import org.openqa.grid.internal.Registry; | |
+import org.openqa.grid.internal.TestSession; | |
+import org.openqa.grid.internal.exception.NewSessionException; | |
+ | |
+/** | |
+ * wrapper around a selenium http request that helps accessing the internal | |
+ * details that are selenium related ( type of protocol, new session request | |
+ * etc ) Also allows to change the content of the request, or read it | |
+ * on the hub. | |
+ * | |
+ */ | |
+public abstract class SeleniumBasedRequest extends HttpServletRequestWrapper { | |
+ | |
+ private byte[] body; | |
+ private final Registry registry; | |
+ private final SeleniumProtocol protocol; | |
+ private final RequestType type; | |
+ private final String encoding = "UTF-8"; | |
+ private final Map<String, Object> desiredCapability; | |
+ | |
+ | |
+ public static SeleniumBasedRequest createFromRequest(HttpServletRequest request, Registry registry) { | |
+ if ("/selenium-server/driver".equals(request.getServletPath())) { | |
+ return new LegacySeleniumRequest(request, registry); | |
+ } else { | |
+ return new WebDriverRequest(request, registry); | |
+ } | |
+ } | |
+ | |
+ | |
+ /*@Deprecated | |
+ public SeleniumBasedRequest(Registry registry,SeleniumProtocol protocol,RequestType type,Map<String, Object> desiredCapability){ | |
+ super(null); | |
+ this.registry = registry; | |
+ this.protocol = protocol; | |
+ this.type = type; | |
+ this.desiredCapability = desiredCapability; | |
+ }*/ | |
+ | |
+ public SeleniumBasedRequest(HttpServletRequest httpServletRequest, Registry registry, | |
+ SeleniumProtocol protocol) { | |
+ super(httpServletRequest); | |
+ try { | |
+ InputStream is = super.getInputStream(); | |
+ body = IOUtils.toByteArray(is); | |
+ } catch (IOException ex) { | |
+ throw new RuntimeException(ex); | |
+ } | |
+ this.protocol = protocol; | |
+ this.registry = registry; | |
+ type = extractRequestType(); | |
+ | |
+ if (type == RequestType.START_SESSION) { | |
+ desiredCapability = extractDesiredCapability(); | |
+ } else { | |
+ desiredCapability = null; | |
+ } | |
+ } | |
+ | |
+ public Registry getRegistry() { | |
+ return registry; | |
+ } | |
+ | |
+ /** | |
+ * @return the type of the request. | |
+ */ | |
+ public abstract RequestType extractRequestType(); | |
+ | |
+ /** | |
+ * Extract the session from the request. This only works for a request that has a session already | |
+ * assigned. It shouldn't be called for a new session request. | |
+ * | |
+ * @return the external session id sent by the remote. Null is the session cannot be found. | |
+ */ | |
+ public abstract ExternalSessionKey extractSession(); | |
+ | |
+ /** | |
+ * Parse the request to extract the desiredCapabilities. For non web driver protocol ( selenium1 ) | |
+ * some mapping will be necessary | |
+ * | |
+ * @return the desired capabilities requested by the client. | |
+ */ | |
+ public abstract Map<String, Object> extractDesiredCapability(); | |
+ | |
+ | |
+ // TODO freynaud remove the TestSession parameter.The listener can modify the | |
+ // original request instead. | |
+ public abstract String getNewSessionRequestedCapability(TestSession session); | |
+ | |
+ | |
+ | |
+ public RequestType getRequestType() { | |
+ return type; | |
+ } | |
+ | |
+ @Override | |
+ public ServletInputStream getInputStream() throws IOException { | |
+ return new ServletInputStreamImpl(new ByteArrayInputStream(body)); | |
+ } | |
+ | |
+ @Override | |
+ public BufferedReader getReader() throws IOException { | |
+ return new BufferedReader(new InputStreamReader(getInputStream(), encoding)); | |
+ } | |
+ | |
+ public String getBody() { | |
+ try { | |
+ Charset charset = Charset.forName(encoding); | |
+ CharsetDecoder decoder = charset.newDecoder(); | |
+ CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(body)); | |
+ return new String(cbuf.toString()); | |
+ } catch (CharacterCodingException e) { | |
+ e.printStackTrace(); | |
+ } | |
+ return null; | |
+ } | |
+ | |
+ public void setBody(String content) { | |
+ body = content.getBytes(); | |
+ } | |
+ | |
+ | |
+ | |
+ public String toString() { | |
+ StringBuilder builder = new StringBuilder(); | |
+ builder.append("method: " + getMethod().toUpperCase() + "\n"); | |
+ builder.append("path: " + getPathInfo() + "\n"); | |
+ if (getBody() != null) { | |
+ builder.append("parameter: " + getBody()); | |
+ } | |
+ return builder.toString(); | |
+ } | |
+ | |
+ public Map<String, Object> getDesiredCapabilities() { | |
+ return desiredCapability; | |
+ } | |
+ | |
+ private class ServletInputStreamImpl extends ServletInputStream { | |
+ | |
+ private InputStream is; | |
+ | |
+ public ServletInputStreamImpl(InputStream is) { | |
+ this.is = is; | |
+ } | |
+ | |
+ public int read() throws IOException { | |
+ return is.read(); | |
+ } | |
+ | |
+ public boolean markSupported() { | |
+ return false; | |
+ } | |
+ | |
+ public synchronized void mark(int i) { | |
+ throw new RuntimeException("not implemented"); | |
+ } | |
+ | |
+ public synchronized void reset() throws IOException { | |
+ throw new RuntimeException("not implemented"); | |
+ } | |
+ } | |
+ | |
+ | |
+ | |
+} | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/Selenium1RequestHandler.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/Selenium1RequestHandler.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/Selenium1RequestHandler.java (working copy) | |
@@ -1,173 +0,0 @@ | |
-/* | |
-Copyright 2011 WebDriver committers | |
-Copyright 2011 Software Freedom Conservancy | |
- | |
-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.openqa.grid.web.servlet.handler; | |
- | |
-import org.openqa.grid.common.RegistrationRequest; | |
-import org.openqa.grid.common.SeleniumProtocol; | |
-import org.openqa.grid.internal.ExternalSessionKey; | |
-import org.openqa.grid.internal.exception.NewSessionException; | |
-import org.openqa.grid.internal.utils.ForwardConfiguration; | |
-import org.openqa.grid.internal.Registry; | |
-import org.openqa.grid.internal.TestSession; | |
-import org.openqa.grid.web.utils.BrowserNameUtils; | |
- | |
-import java.io.IOException; | |
-import java.io.UnsupportedEncodingException; | |
-import java.net.URLDecoder; | |
-import java.net.URLEncoder; | |
-import java.util.HashMap; | |
-import java.util.Map; | |
-import java.util.logging.Logger; | |
- | |
-import javax.servlet.http.HttpServletRequest; | |
-import javax.servlet.http.HttpServletResponse; | |
- | |
-/** | |
- * Handler processing the selenium1 based requests. Each request body has to be read to get the | |
- * sessionId at least. | |
- */ | |
-public class Selenium1RequestHandler extends RequestHandler { | |
- | |
- private static final Logger log = Logger.getLogger(Selenium1RequestHandler.class.getName()); | |
- | |
- Selenium1RequestHandler(HttpServletRequest request, HttpServletResponse response, | |
- Registry registry) { | |
- super(request, response, registry); | |
- if (getRequestBody() == null) { | |
- throw new InstantiationError( | |
- "Cannot create a selenium1 request handler from a request without body"); | |
- } | |
- } | |
- | |
- @Override | |
- public RequestType extractRequestType() { | |
- if (getRequestBody().contains("cmd=getNewBrowserSession")) { | |
- return RequestType.START_SESSION; | |
- } else if (getRequestBody().contains("cmd=testComplete")) { | |
- return RequestType.STOP_SESSION; | |
- } else { | |
- return RequestType.REGULAR; | |
- } | |
- } | |
- | |
- @Override | |
- public ExternalSessionKey extractSession() { | |
- if (getRequestType() == RequestType.START_SESSION) { | |
- throw new IllegalAccessError("Cannot call that method of a new session request."); | |
- } | |
- // for selenium 1, the url is ignored. The session has to be read from | |
- // the request body. | |
- String command = getRequestBody(); | |
- String[] pieces = command.split("&"); | |
- ExternalSessionKey externalSessionKey; | |
- for (String piece : pieces) { | |
- externalSessionKey = ExternalSessionKey.fromSe1Request( piece); | |
- if (externalSessionKey != null){ | |
- return externalSessionKey; | |
- } | |
- } | |
- return null; | |
- | |
- } | |
- | |
- @Override | |
- public Map<String, Object> extractDesiredCapability() { | |
- if (getRequestType() != RequestType.START_SESSION) { | |
- throw new Error("the desired capability is only present in the new session requests."); | |
- } | |
- String[] pieces = getRequestBody().split("&"); | |
- for (String piece : pieces) { | |
- try { | |
- piece = URLDecoder.decode(piece, "UTF-8"); | |
- } catch (UnsupportedEncodingException e) { | |
- } | |
- if (piece.startsWith("1=")) { | |
- String envt = piece.replace("1=", ""); | |
- Map<String, Object> cap = new HashMap<String, Object>(); | |
- // TODO freynaud : more splitting, like trying to guess the | |
- // plateform or version ? | |
- | |
- // We don't want to process Grid 1.0 environment names because | |
- // they use an explicit mapping | |
- // to a browser launcher string. | |
- if (getRegistry().getConfiguration().getGrid1Mapping().containsKey(envt)) { | |
- cap.put(RegistrationRequest.BROWSER, envt); | |
- } | |
- | |
- // Otherwise, process the environment string to extract the | |
- // target browser and platform. | |
- else { | |
- cap.putAll(BrowserNameUtils.parseGrid2Environment(envt)); | |
- } | |
- | |
- return cap; | |
- } | |
- } | |
- | |
- throw new RuntimeException("Error"); | |
- } | |
- | |
- // TODO freynaud do some real parsing here instead. BrowserString to | |
- // Capabilities service or so. | |
- @Override | |
- public ExternalSessionKey forwardNewSessionRequestAndUpdateRegistry(TestSession session) throws NewSessionException { | |
- String responseBody; | |
- | |
- try { | |
- String body = getRequestBody(); | |
- String[] pieces = body.split("&"); | |
- StringBuilder builder = new StringBuilder(); | |
- | |
- for (String piece : pieces) { | |
- if (piece.startsWith("1=")) { | |
- piece = URLDecoder.decode(piece, "UTF-8"); | |
- String parts[] = piece.split("1="); | |
- | |
- // We don't want to process Grid 1.0 environment names | |
- // because they use an explicit mapping | |
- // to a browser launcher string. | |
- if (getRegistry().getConfiguration().getGrid1Mapping().containsKey(parts[1])) { | |
- piece = | |
- String.format( | |
- "1=%s", | |
- URLEncoder.encode( | |
- BrowserNameUtils.lookupGrid1Environment(parts[1], getRegistry()), "UTF-8")); | |
- } | |
- | |
- // Otherwise, the requested environment includes the browser | |
- // name before the space. | |
- else { | |
- piece = | |
- (String) BrowserNameUtils.parseGrid2Environment(piece).get( | |
- RegistrationRequest.BROWSER); | |
- } | |
- } | |
- builder.append(piece).append("&"); | |
- } | |
- | |
- ForwardConfiguration config = new ForwardConfiguration(); | |
- config.setProtocol(SeleniumProtocol.Selenium); | |
- config.setNewSessionRequest(true); | |
- config.setContentOverWrite(builder.toString()); | |
- responseBody = session.forward(getRequest(), getResponse(), config); | |
- } catch (IOException e) { | |
- throw new NewSessionException("Error forwarding the request " + e.getMessage(),e); | |
- } | |
- return ExternalSessionKey.fromResponseBody(responseBody); | |
- } | |
-} | |
Index: java/server/src/org/openqa/grid/internal/Registry.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/internal/Registry.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/internal/Registry.java (working copy) | |
@@ -238,12 +238,12 @@ | |
this.hub = hub; | |
} | |
- public void addNewSessionRequest(RequestHandler request) { | |
+ public void addNewSessionRequest(RequestHandler handler) { | |
try { | |
lock.lock(); | |
- proxies.verifyAbilityToHandleDesiredCapabilities(request.getDesiredCapabilities()); | |
- newSessionQueue.add(request); | |
+ proxies.verifyAbilityToHandleDesiredCapabilities(handler.getRequest().getDesiredCapabilities()); | |
+ newSessionQueue.add(handler); | |
fireMatcherStateChanged(); | |
} finally { | |
lock.unlock(); | |
@@ -278,12 +278,12 @@ | |
} | |
- private boolean takeRequestHandler(RequestHandler request) { | |
- final TestSession session = proxies.getNewSession(request.getDesiredCapabilities()); | |
+ private boolean takeRequestHandler(RequestHandler handler) { | |
+ final TestSession session = proxies.getNewSession(handler.getRequest().getDesiredCapabilities()); | |
final boolean sessionCreated = session != null; | |
if (sessionCreated) { | |
activeTestSessions.add(session); | |
- request.bindSession(session); | |
+ handler.bindSession(session); | |
} | |
return sessionCreated; | |
} | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequest.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequest.java (revision 0) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/WebDriverRequest.java (revision 0) | |
@@ -0,0 +1,78 @@ | |
+package org.openqa.grid.web.servlet.handler; | |
+ | |
+import java.util.HashMap; | |
+import java.util.Iterator; | |
+import java.util.Map; | |
+ | |
+import javax.servlet.http.HttpServletRequest; | |
+ | |
+import org.json.JSONException; | |
+import org.json.JSONObject; | |
+import org.openqa.grid.common.SeleniumProtocol; | |
+import org.openqa.grid.common.exception.GridException; | |
+import org.openqa.grid.internal.ExternalSessionKey; | |
+import org.openqa.grid.internal.Registry; | |
+import org.openqa.grid.internal.TestSession; | |
+import org.openqa.grid.internal.exception.NewSessionException; | |
+ | |
+public class WebDriverRequest extends SeleniumBasedRequest { | |
+ | |
+ public WebDriverRequest(HttpServletRequest httpServletRequest, Registry registry) { | |
+ super(httpServletRequest, registry, SeleniumProtocol.WebDriver); | |
+ } | |
+ | |
+ @Override | |
+ public RequestType extractRequestType() { | |
+ if ("/session".equals(getPathInfo())) { | |
+ return RequestType.START_SESSION; | |
+ } else if (getMethod().equalsIgnoreCase("DELETE")) { | |
+ ExternalSessionKey externalKey = ExternalSessionKey.fromWebDriverRequest(getPathInfo()); | |
+ if (getPathInfo().endsWith("/session/" + externalKey.getKey())) { | |
+ return RequestType.STOP_SESSION; | |
+ } | |
+ } | |
+ return RequestType.REGULAR; | |
+ } | |
+ | |
+ @Override | |
+ public ExternalSessionKey extractSession() { | |
+ if (getRequestType() == RequestType.START_SESSION) { | |
+ throw new IllegalAccessError("Cannot call that method of a new session request."); | |
+ } | |
+ String path = getPathInfo(); | |
+ return ExternalSessionKey.fromWebDriverRequest(path); | |
+ } | |
+ | |
+ @Override | |
+ public Map<String, Object> extractDesiredCapability() { | |
+ String json = getBody(); | |
+ Map<String, Object> desiredCapability = new HashMap<String, Object>(); | |
+ try { | |
+ JSONObject map = new JSONObject(json); | |
+ JSONObject dc = map.getJSONObject("desiredCapabilities"); | |
+ for (Iterator iterator = dc.keys(); iterator.hasNext();) { | |
+ String key = (String) iterator.next(); | |
+ Object value = dc.get(key); | |
+ if (value == JSONObject.NULL) { | |
+ value = null; | |
+ } | |
+ desiredCapability.put(key, value); | |
+ } | |
+ } catch (JSONException e) { | |
+ throw new GridException("Cannot extract a capabilities from the request " + json); | |
+ } | |
+ return desiredCapability; | |
+ } | |
+ | |
+ @Override | |
+ public String getNewSessionRequestedCapability(TestSession session) { | |
+ try { | |
+ JSONObject c = new JSONObject(); | |
+ c.put("desiredCapabilities", session.getRequestedCapabilities()); | |
+ String content = c.toString(); | |
+ return content; | |
+ } catch (JSONException e) { | |
+ throw new NewSessionException("Error with the request " + e.getMessage(),e); | |
+ } | |
+ } | |
+} | |
Index: java/server/src/org/openqa/grid/internal/TestSession.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/internal/TestSession.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/internal/TestSession.java (working copy) | |
@@ -38,6 +38,10 @@ | |
import org.openqa.grid.internal.listeners.CommandListener; | |
import org.openqa.grid.internal.utils.ForwardConfiguration; | |
import org.openqa.grid.web.Hub; | |
+import org.openqa.grid.web.servlet.handler.LegacySeleniumRequest; | |
+import org.openqa.grid.web.servlet.handler.RequestType; | |
+import org.openqa.grid.web.servlet.handler.SeleniumBasedRequest; | |
+import org.openqa.grid.web.servlet.handler.WebDriverRequest; | |
import java.io.BufferedReader; | |
import java.io.ByteArrayInputStream; | |
@@ -188,9 +192,9 @@ | |
/** | |
* Forward the request to the remote, execute the TestSessionListeners if applicable. | |
*/ | |
- public void forward(HttpServletRequest request, HttpServletResponse response) throws IOException { | |
+ /* public void forward(HttpServletRequest request, HttpServletResponse response) throws IOException { | |
forward(request, response, new ForwardConfiguration()); | |
- } | |
+ }*/ | |
private HttpClient getClient() { | |
return slot.getProxy().getHttpClientFactory().getGridHttpClient(); | |
@@ -200,19 +204,20 @@ | |
* @param config for special cases of forwards. Typically is the content has to be intercepted, or | |
* if the hub has to be updated before the new session request is forwarded. | |
*/ | |
- public String forward(HttpServletRequest request, HttpServletResponse response, | |
- ForwardConfiguration config) throws IOException { | |
+ public String forward(SeleniumBasedRequest request, HttpServletResponse response/*, | |
+ ForwardConfiguration config*/) throws IOException { | |
String res = null; | |
forwardingRequest = true; | |
try { | |
if (slot.getProxy() instanceof CommandListener) { | |
+ System.out.println(request); | |
((CommandListener) slot.getProxy()).beforeCommand(this, request, response); | |
} | |
lastActivity = timeSource.currentTimeInMillis(); | |
- HttpRequest proxyRequest = prepareProxyRequest(request, config); | |
+ HttpRequest proxyRequest = prepareProxyRequest(request/*, config*/); | |
HttpResponse proxyResponse = sendRequestToNode(proxyRequest); | |
@@ -221,21 +226,21 @@ | |
response.setStatus(proxyResponse.getStatusLine().getStatusCode()); | |
processResponseHeaders(request, response, slot.getRemoteURL(), proxyResponse); | |
- updateHubIfNewWebDriverSession(config, proxyResponse); | |
+ updateHubIfNewWebDriverSession(request, proxyResponse); | |
HttpEntity responseBody = proxyResponse.getEntity(); | |
if (responseBody != null) { | |
try { | |
InputStream in = responseBody.getContent(); | |
- boolean isSeleniumNewSessionRequest = | |
- config.isNewSessionRequest() && config.getProtocol() == SeleniumProtocol.Selenium; | |
- if (config.isBodyHasToBeRead() || isSeleniumNewSessionRequest) { | |
+ //boolean isSeleniumNewSessionRequest = | |
+ // config.isNewSessionRequest() && config.getProtocol() == SeleniumProtocol.Selenium; | |
+ //if (config.isBodyHasToBeRead() || isSeleniumNewSessionRequest) { | |
+ if (request.getRequestType() == RequestType.START_SESSION && | |
+ request instanceof LegacySeleniumRequest) { | |
res = getResponseUtf8Content(in); | |
- | |
- if (isSeleniumNewSessionRequest) { | |
- updateHubNewSeleniumSession(res); | |
- } | |
+ updateHubNewSeleniumSession(res); | |
+ | |
in = new ByteArrayInputStream(res.getBytes("UTF-8")); | |
} | |
@@ -263,9 +268,10 @@ | |
setExternalKey(key); | |
} | |
- private void updateHubIfNewWebDriverSession(ForwardConfiguration config, | |
+ private void updateHubIfNewWebDriverSession(SeleniumBasedRequest request, | |
HttpResponse proxyResponse) { | |
- if (config.isNewSessionRequest() && config.getProtocol() == SeleniumProtocol.WebDriver) { | |
+ if (request.getRequestType() == RequestType.START_SESSION | |
+ && request instanceof WebDriverRequest) { | |
Header h = proxyResponse.getFirstHeader("Location"); | |
if (h == null) { | |
throw new GridException( | |
@@ -285,7 +291,7 @@ | |
return client.execute(host, proxyRequest); | |
} | |
- private HttpRequest prepareProxyRequest(HttpServletRequest request, ForwardConfiguration config) | |
+ private HttpRequest prepareProxyRequest(HttpServletRequest request/*, ForwardConfiguration config*/) | |
throws IOException { | |
URL remoteURL = slot.getRemoteURL(); | |
@@ -305,12 +311,12 @@ | |
} | |
HttpRequest proxyRequest; | |
- if (config.getContentOverWrite() != null) { | |
+ /*if (config.getContentOverWrite() != null) { | |
BasicHttpEntityEnclosingRequest r = | |
new BasicHttpEntityEnclosingRequest(request.getMethod(), uri); | |
r.setEntity(new StringEntity(config.getContentOverWrite())); | |
proxyRequest = r; | |
- } else if (body != null) { | |
+ } else */if (body != null) { | |
BasicHttpEntityEnclosingRequest r = | |
new BasicHttpEntityEnclosingRequest(request.getMethod(), uri); | |
r.setEntity(new InputStreamEntity(body, request.getContentLength())); | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/LegacySeleniumRequest.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/LegacySeleniumRequest.java (revision 0) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/LegacySeleniumRequest.java (revision 0) | |
@@ -0,0 +1,134 @@ | |
+package org.openqa.grid.web.servlet.handler; | |
+ | |
+import java.io.UnsupportedEncodingException; | |
+import java.net.URLDecoder; | |
+import java.net.URLEncoder; | |
+import java.util.HashMap; | |
+import java.util.Map; | |
+ | |
+import javax.servlet.http.HttpServletRequest; | |
+ | |
+import org.openqa.grid.common.RegistrationRequest; | |
+import org.openqa.grid.common.SeleniumProtocol; | |
+import org.openqa.grid.internal.ExternalSessionKey; | |
+import org.openqa.grid.internal.Registry; | |
+import org.openqa.grid.internal.TestSession; | |
+import org.openqa.grid.internal.exception.NewSessionException; | |
+import org.openqa.grid.web.utils.BrowserNameUtils; | |
+ | |
+public class LegacySeleniumRequest extends SeleniumBasedRequest { | |
+ | |
+ public LegacySeleniumRequest(HttpServletRequest httpServletRequest, Registry registry) { | |
+ super(httpServletRequest, registry, SeleniumProtocol.Selenium); | |
+ | |
+ } | |
+ | |
+ @Override | |
+ public RequestType extractRequestType() { | |
+ if (getBody().contains("cmd=getNewBrowserSession")) { | |
+ return RequestType.START_SESSION; | |
+ } else if (getBody().contains("cmd=testComplete")) { | |
+ return RequestType.STOP_SESSION; | |
+ } else { | |
+ return RequestType.REGULAR; | |
+ } | |
+ | |
+ } | |
+ | |
+ @Override | |
+ public ExternalSessionKey extractSession() { | |
+ if (getRequestType() == RequestType.START_SESSION) { | |
+ throw new IllegalAccessError("Cannot call that method of a new session request."); | |
+ } | |
+ // for selenium 1, the url is ignored. The session has to be read from | |
+ // the request body. | |
+ String command = getBody(); | |
+ String[] pieces = command.split("&"); | |
+ ExternalSessionKey externalSessionKey; | |
+ for (String piece : pieces) { | |
+ externalSessionKey = ExternalSessionKey.fromSe1Request(piece); | |
+ if (externalSessionKey != null) { | |
+ return externalSessionKey; | |
+ } | |
+ } | |
+ return null; | |
+ } | |
+ | |
+ @Override | |
+ public Map<String, Object> extractDesiredCapability() { | |
+ if (getRequestType() != RequestType.START_SESSION) { | |
+ throw new Error("the desired capability is only present in the new session requests."); | |
+ } | |
+ String[] pieces = getBody().split("&"); | |
+ for (String piece : pieces) { | |
+ try { | |
+ piece = URLDecoder.decode(piece, "UTF-8"); | |
+ } catch (UnsupportedEncodingException e) {} | |
+ if (piece.startsWith("1=")) { | |
+ String envt = piece.replace("1=", ""); | |
+ Map<String, Object> cap = new HashMap<String, Object>(); | |
+ // TODO freynaud : more splitting, like trying to guess the | |
+ // plateform or version ? | |
+ | |
+ // We don't want to process Grid 1.0 environment names because | |
+ // they use an explicit mapping | |
+ // to a browser launcher string. | |
+ if (getRegistry().getConfiguration().getGrid1Mapping().containsKey(envt)) { | |
+ cap.put(RegistrationRequest.BROWSER, envt); | |
+ } | |
+ | |
+ // Otherwise, process the environment string to extract the | |
+ // target browser and platform. | |
+ else { | |
+ cap.putAll(BrowserNameUtils.parseGrid2Environment(envt)); | |
+ } | |
+ | |
+ return cap; | |
+ } | |
+ } | |
+ | |
+ throw new RuntimeException("Error"); | |
+ } | |
+ | |
+ @Override | |
+ public String getNewSessionRequestedCapability(TestSession session) { | |
+ try { | |
+ String body = getBody(); | |
+ String[] pieces = body.split("&"); | |
+ StringBuilder builder = new StringBuilder(); | |
+ | |
+ for (String piece : pieces) { | |
+ if (piece.startsWith("1=")) { | |
+ piece = URLDecoder.decode(piece, "UTF-8"); | |
+ String parts[] = piece.split("1="); | |
+ | |
+ // We don't want to process Grid 1.0 environment names | |
+ // because they use an explicit mapping | |
+ // to a browser launcher string. | |
+ if (getRegistry().getConfiguration().getGrid1Mapping().containsKey(parts[1])) { | |
+ piece = | |
+ String.format( | |
+ "1=%s", | |
+ URLEncoder.encode( | |
+ BrowserNameUtils.lookupGrid1Environment(parts[1], getRegistry()), "UTF-8")); | |
+ } | |
+ | |
+ // Otherwise, the requested environment includes the browser | |
+ // name before the space. | |
+ else { | |
+ piece = | |
+ (String) BrowserNameUtils.parseGrid2Environment(piece).get( | |
+ RegistrationRequest.BROWSER); | |
+ } | |
+ } | |
+ builder.append(piece).append("&"); | |
+ } | |
+ return builder.toString(); | |
+ } catch (UnsupportedEncodingException ignore) { | |
+ | |
+ } | |
+ throw new NewSessionException("Error with the request "); | |
+ | |
+ } | |
+ | |
+} | |
Index: java/server/src/org/openqa/grid/web/servlet/DriverServlet.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/DriverServlet.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/web/servlet/DriverServlet.java (working copy) | |
@@ -77,7 +77,7 @@ | |
throws IOException { | |
RequestHandler req = null; | |
try { | |
- req = RequestHandler.createHandler(request, response, getRegistry()); | |
+ req = new RequestHandler(request, response, getRegistry()); | |
req.process(); | |
} catch (Throwable e) { | |
Index: java/server/src/org/openqa/grid/web/servlet/handler/RequestHandler.java | |
=================================================================== | |
--- java/server/src/org/openqa/grid/web/servlet/handler/RequestHandler.java (revision 15924) | |
+++ java/server/src/org/openqa/grid/web/servlet/handler/RequestHandler.java (working copy) | |
@@ -17,23 +17,7 @@ | |
package org.openqa.grid.web.servlet.handler; | |
-import org.openqa.grid.common.exception.ClientGoneException; | |
-import org.openqa.grid.common.exception.GridException; | |
-import org.openqa.grid.internal.ExternalSessionKey; | |
-import org.openqa.grid.internal.Registry; | |
-import org.openqa.grid.internal.RemoteProxy; | |
-import org.openqa.grid.internal.SessionTerminationReason; | |
-import org.openqa.grid.internal.TestSession; | |
-import org.openqa.grid.internal.exception.NewSessionException; | |
-import org.openqa.grid.internal.listeners.Prioritizer; | |
-import org.openqa.grid.internal.listeners.TestSessionListener; | |
-import org.openqa.grid.internal.utils.ForwardConfiguration; | |
- | |
-import java.io.BufferedReader; | |
import java.io.IOException; | |
-import java.io.InputStream; | |
-import java.io.InputStreamReader; | |
-import java.io.UnsupportedEncodingException; | |
import java.util.Map; | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.TimeUnit; | |
@@ -44,7 +28,18 @@ | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
+import org.openqa.grid.common.exception.ClientGoneException; | |
+import org.openqa.grid.common.exception.GridException; | |
+import org.openqa.grid.internal.ExternalSessionKey; | |
+import org.openqa.grid.internal.Registry; | |
+import org.openqa.grid.internal.RemoteProxy; | |
+import org.openqa.grid.internal.SessionTerminationReason; | |
+import org.openqa.grid.internal.TestSession; | |
+import org.openqa.grid.internal.exception.NewSessionException; | |
+import org.openqa.grid.internal.listeners.Prioritizer; | |
+import org.openqa.grid.internal.listeners.TestSessionListener; | |
+ | |
/** | |
* Base stuff to handle the request coming from a remote. Ideally, there should be only 1 concrete | |
* class, but to support both legacy selenium1 and web driver, 2 classes are needed. <p/> {@link | |
@@ -55,14 +50,12 @@ | |
* thread. The instance is also accessed by the matcher thread. | |
*/ | |
@SuppressWarnings("JavaDoc") | |
-public abstract class RequestHandler implements Comparable<RequestHandler> { | |
+public class RequestHandler implements Comparable<RequestHandler> { | |
private final Registry registry; | |
- private final HttpServletRequest request; | |
+ private final SeleniumBasedRequest request; | |
private final HttpServletResponse response; | |
- private String body = null; | |
- private boolean bodyHasBeenRead = false; | |
private volatile Map<String, Object> desiredCapabilities = null; | |
private RequestType requestType = null; | |
private volatile TestSession session = null; | |
@@ -73,73 +66,46 @@ | |
private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); | |
private final Thread waitingThread; | |
- /** | |
- * Detect what kind of protocol ( selenium1 vs webdriver ) is used by the request and create the | |
- * associated handler. | |
- */ | |
- public static RequestHandler createHandler(HttpServletRequest request, | |
- HttpServletResponse response, Registry registry) { | |
- if (isSeleniumProtocol(request)) { | |
- return new Selenium1RequestHandler(request, response, registry); | |
- } else { | |
- return new WebDriverRequestHandler(request, response, registry); | |
- } | |
- } | |
+ | |
+ | |
- protected RequestHandler(HttpServletRequest request, HttpServletResponse response, | |
- Registry registry) { | |
- this.request = request; | |
+ public RequestHandler(HttpServletRequest request, HttpServletResponse response, | |
+ Registry registry) { | |
+ this.request = SeleniumBasedRequest.createFromRequest(request, registry);; | |
this.response = response; | |
this.registry = registry; | |
this.waitingThread = Thread.currentThread(); | |
} | |
- /** | |
- * @return the type of the request. | |
- */ | |
- public abstract RequestType extractRequestType(); | |
- /** | |
- * Extract the session from the request. This only works for a request that has a session already | |
- * assigned. It shouldn't be called for a new session request. | |
- * | |
- * @return the external session id sent by the remote. Null is the session cannot be found. | |
- */ | |
- public abstract ExternalSessionKey extractSession(); | |
/** | |
- * Parse the request to extract the desiredCapabilities. For non web driver protocol ( selenium1 ) | |
- * some mapping will be necessary | |
- * | |
- * @return the desired capabilities requested by the client. | |
- */ | |
- public abstract Map<String, Object> extractDesiredCapability(); | |
- | |
- /** | |
* Forward the new session request to the TestSession that has been assigned, and parse the | |
* response to extract and return the external key assigned by the remote. | |
* | |
- * @return the external key sent by the remote. | |
* @throws NewSessionException in case anything wrong happens during the new session process. | |
*/ | |
- public abstract ExternalSessionKey forwardNewSessionRequestAndUpdateRegistry(TestSession session) | |
- throws NewSessionException; | |
+ public void forwardNewSessionRequestAndUpdateRegistry(TestSession session) | |
+ throws NewSessionException { | |
+ try { | |
+ String content = request.getNewSessionRequestedCapability(session); | |
+ getRequest().setBody(content); | |
+ session.forward(getRequest(), getResponse()); | |
+ } catch (IOException e) { | |
+ //log.warning("Error forwarding the request " + e.getMessage()); | |
+ throw new NewSessionException("Error forwarding the request " + e.getMessage(), e); | |
+ } | |
+ } | |
protected void forwardRequest(TestSession session, RequestHandler handler) throws IOException { | |
- if (bodyHasBeenRead) { | |
- ForwardConfiguration config = new ForwardConfiguration(); | |
- config.setContentOverWrite(getRequestBody()); | |
- session.forward(request, response, config); | |
- } else { | |
- session.forward(request, response); | |
- } | |
+ session.forward(request, response); | |
} | |
/** | |
* forwards the request to the remote, allocating / releasing the resources if necessary. | |
*/ | |
public void process() { | |
- switch (getRequestType()) { | |
+ switch (request.getRequestType()) { | |
case START_SESSION: | |
try { | |
registry.addNewSessionRequest(this); | |
@@ -157,24 +123,24 @@ | |
if (session == null) { | |
ExternalSessionKey sessionKey = null; | |
try { | |
- sessionKey = extractSession(); | |
- } catch (RuntimeException ignore) { | |
- } | |
+ sessionKey = request.extractSession(); | |
+ } catch (RuntimeException ignore) {} | |
throw new GridException("Session [" + sessionKey + "] not available - " | |
- + registry.getActiveSessions()); | |
+ + registry.getActiveSessions()); | |
} | |
try { | |
forwardRequest(session, this); | |
} catch (Throwable t) { | |
- SessionTerminationReason reason = t instanceof ClientGoneException ? | |
- SessionTerminationReason.CLIENT_GONE : | |
- SessionTerminationReason.FORWARDING_TO_NODE_FAILED; | |
+ SessionTerminationReason reason = | |
+ t instanceof ClientGoneException | |
+ ? SessionTerminationReason.CLIENT_GONE | |
+ : SessionTerminationReason.FORWARDING_TO_NODE_FAILED; | |
log.log(Level.SEVERE, "cannot forward the request " + t.getMessage(), t); | |
registry.terminate(session, reason); | |
throw new GridException("cannot forward the request " + t.getMessage(), t); | |
} | |
- if (getRequestType() == RequestType.STOP_SESSION) { | |
+ if (request.getRequestType() == RequestType.STOP_SESSION) { | |
registry.terminate(session, SessionTerminationReason.CLIENT_STOPPED_SESSION); | |
} | |
break; | |
@@ -192,7 +158,7 @@ | |
} | |
} | |
- | |
+ | |
/** | |
* calls the TestSessionListener is the proxy for that node has one specified. | |
* | |
@@ -243,36 +209,13 @@ | |
* reads the input stream of the request and returns its content. | |
*/ | |
protected String getRequestBody() { | |
- if (!bodyHasBeenRead) { | |
- bodyHasBeenRead = true; | |
- StringBuilder sb = new StringBuilder(); | |
- String line; | |
- try { | |
- InputStream is = request.getInputStream(); | |
- if (is == null) { | |
- return null; | |
- } | |
- BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); | |
- while ((line = reader.readLine()) != null) { | |
- // TODO freynaud bug ? | |
- sb.append(line);/* .append("\n"); */ | |
- | |
- } | |
- is.close(); | |
- } catch (UnsupportedEncodingException e) { | |
- throw new RuntimeException(e); | |
- } catch (IOException e) { | |
- throw new RuntimeException(e); | |
- } | |
- body = sb.toString(); | |
- } | |
- return body; | |
+ return request.getBody(); | |
} | |
/** | |
* the HttpServletRequest this hanlder is processing. | |
*/ | |
- public HttpServletRequest getRequest() { | |
+ public SeleniumBasedRequest getRequest() { | |
return request; | |
} | |
@@ -283,36 +226,19 @@ | |
return response; | |
} | |
- public Map<String, Object> getDesiredCapabilities() { | |
- if (desiredCapabilities == null) { | |
- desiredCapabilities = extractDesiredCapability(); | |
- } | |
- return desiredCapabilities; | |
- } | |
- protected void setDesiredCapabilities(Map<String, Object> desiredCapabilities) { | |
- this.desiredCapabilities = desiredCapabilities; | |
- } | |
public int compareTo(RequestHandler o) { | |
Prioritizer prioritizer = registry.getPrioritizer(); | |
if (prioritizer != null) { | |
- return prioritizer.compareTo(this.getDesiredCapabilities(), o.getDesiredCapabilities()); | |
+ return prioritizer.compareTo(this.getRequest().getDesiredCapabilities(), o.getRequest() | |
+ .getDesiredCapabilities()); | |
} else { | |
return 0; | |
} | |
} | |
- protected RequestType getRequestType() { | |
- if (requestType == null) { | |
- requestType = extractRequestType(); | |
- } | |
- return requestType; | |
- } | |
- protected void setRequestType(RequestType requestType) { | |
- this.requestType = requestType; | |
- } | |
protected void setSession(TestSession session) { | |
this.session = session; | |
@@ -325,7 +251,7 @@ | |
protected TestSession getSession() { | |
if (session == null) { | |
- ExternalSessionKey externalKey = extractSession(); | |
+ ExternalSessionKey externalKey = request.extractSession(); | |
session = registry.getExistingSession(externalKey); | |
} | |
return session; | |
@@ -352,7 +278,6 @@ | |
public String toString() { | |
StringBuilder b = new StringBuilder(); | |
b.append("session :").append(session).append(" , "); | |
- b.append("cap : ").append(getDesiredCapabilities()); | |
b.append("\n"); | |
return b.toString(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment