/*
* Copyright 2012-2014 eBay Software Foundation and selendroid committers.
*
* 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 io.selendroid.standalone.server;
import io.selendroid.server.common.BaseRequestHandler;
import io.selendroid.server.common.BaseServlet;
import io.selendroid.server.common.Response;
import io.selendroid.server.common.SelendroidResponse;
import io.selendroid.server.common.UiResponse;
import io.selendroid.server.common.http.HttpRequest;
import io.selendroid.server.common.http.HttpResponse;
import io.selendroid.standalone.SelendroidConfiguration;
import io.selendroid.standalone.server.handler.*;
import io.selendroid.standalone.server.model.SelendroidStandaloneDriver;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SelendroidServlet extends BaseServlet {
private static final Logger log = Logger.getLogger(SelendroidServlet.class.getName());
protected Map<String, BaseRequestHandler> redirectHandler = new HashMap<String, BaseRequestHandler>();
private SelendroidStandaloneDriver driver;
private SelendroidConfiguration conf;
public SelendroidServlet(SelendroidStandaloneDriver driver, SelendroidConfiguration conf) {
this.driver = driver;
this.conf = conf;
init();
}
protected void init() {
register(postHandler, new CreateSessionHandler("/wd/hub/session"));
register(getHandler, new ListSessionsHandler("/wd/hub/sessions"));
register(getHandler, new GetCapabilities("/wd/hub/session/:sessionId"));
register(getHandler, new GetLogTypes("/wd/hub/session/:sessionId/log/types"));
register(postHandler, new GetLogs("/wd/hub/session/:sessionId/log"));
if (!conf.isDeviceScreenshot()) {
register(getHandler, new CaptureScreenshot("/wd/hub/session/:sessionId/screenshot"));
} // otherwise the request will be automatically forwarded to the device
register(getHandler, new InspectorTreeHandler("/inspector/session/:sessionId/tree"));
register(getHandler, new InspectorScreenshotHandler("/inspector/session/:sessionId/screenshot"));
register(getHandler, new InspectorUiHandler("/inspector/session/:sessionId"));
register(deleteHandler, new DeleteSessionHandler("/wd/hub/session/:sessionId"));
register(redirectHandler, new ProxyToDeviceHandler("/wd/hub/session/"));
register(postHandler, new GetLogs("/wd/hub/session/:sessionId/log"));
register(postHandler, new AdbSendKeyEvent("/wd/hub/session/:sessionId/selendroid/adb/sendKeyEvent"));
register(postHandler, new AdbSendText("/wd/hub/session/:sessionId/selendroid/adb/sendText"));
register(postHandler, new AdbTap("/wd/hub/session/:sessionId/selendroid/adb/tap"));
register(postHandler, new AdbExecuteShellCommand(
"/wd/hub/session/:sessionId/selendroid/adb/executeShellCommand"));
register(postHandler, new NetworkConnectionHandler("/wd/hub/session/:sessionId/network_connection"));
}
@Override
public void handleRequest(HttpRequest request, HttpResponse response,
BaseRequestHandler foundHandler) {
BaseRequestHandler handler = null;
if ("/favicon.ico".equals(request.uri()) && foundHandler == null) {
response.setStatus(404);
response.end();
return;
}
if ("/inspector/".equals(request.uri()) || "/inspector".equals(request.uri())) {
if (driver.getActiveSessions().isEmpty()) {
response.setStatus(200);
response
.setContent("Selendroid inspector can only be used if there is an active test session running. "
+ "To start a test session, add a break point into your test code and run the test in debug mode.");
response.end();
return;
} else {
// response.setStatus(302);
String session = driver.getActiveSessions().get(0).getSessionId();
String newSessionUri =
"http://" + request.header("Host") + "/inspector/session/" + session + "/";
log.info("new Inspector URL: " + newSessionUri);
response.sendTemporaryRedirect(newSessionUri);
response.end();
return;
}
}
if (foundHandler == null) {
if (!redirectHandler.isEmpty()) {
// trying to find an redirect handler
for (Map.Entry<String, BaseRequestHandler> entry : redirectHandler.entrySet()) {
if (request.uri().startsWith(entry.getKey())) {
String sessionId =
getParameter("/wd/hub/session/:sessionId", request.uri(), ":sessionId", false);
handler = entry.getValue();
if (driver.isValidSession(sessionId)) {
request.data().put(SESSION_ID_KEY, sessionId);
}
}
}
}
if (handler == null) {
response.setStatus(404);
response.end();
return;
}
} else {
handler = foundHandler;
}
String sessionId = getParameter(handler.getMappedUri(), request.uri(), ":sessionId");
if (sessionId != null) {
request.data().put(SESSION_ID_KEY, sessionId);
}
request.data().put(DRIVER_KEY, driver);
Response result;
try {
result = handler.handle(request);
} catch (Exception e) {
log.log(Level.SEVERE, "Error handling request", e);
replyWithServerError(response);
return;
}
if (result instanceof SelendroidResponse) {
handleResponse(request, response, (SelendroidResponse) result);
} else if (result instanceof JsResult) {
JsResult js = (JsResult) result;
response.setContentType("application/x-javascript");
response.setEncoding(Charset.forName("UTF-8"));
response.setContent(js.render());
response.end();
} else if (result instanceof UiResponse) {
UiResponse uiResponse = (UiResponse) result;
response.setEncoding(Charset.forName("UTF-8"));
response.setStatus(200);
if (uiResponse != null) {
if (uiResponse.getObject() instanceof byte[]) {
response.setContentType("image/png");
byte[] data = (byte[]) uiResponse.getObject();
response.setContent(data);
} else {
response.setContentType("text/html");
String resultString = uiResponse.render();
response.setContent(resultString);
}
}
response.end();
} else {
log.log(Level.SEVERE, "Unknown response type: " + result.getClass().getSimpleName());
replyWithServerError(response);
}
}
}