Java tutorial
/* * Copyright 2012 ios-driver 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 org.uiautomation.ios.mobileSafari; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.dom4j.Document; import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.json.JSONObject; import org.uiautomation.ios.mobileSafari.events.ChildNodeRemoved; import org.uiautomation.ios.mobileSafari.events.Event; import org.uiautomation.ios.mobileSafari.events.EventFactory; import org.uiautomation.ios.mobileSafari.events.inserted.ChildIframeInserted; public class DefaultMessageHandler implements MessageHandler { private final List<JSONObject> responses = new CopyOnWriteArrayList<JSONObject>(); private final EventListener listener; private Thread t; private static boolean showIgnoredMessaged = false; private static final Logger log = Logger.getLogger(DefaultMessageHandler.class.getName()); public DefaultMessageHandler(EventListener listener) { this.listener = listener; } @Override public void handle(final String msg) { Thread t = new Thread(new Runnable() { @Override public void run() { process(msg); } }); t.start(); } private void process(String rawMessage) { try { JSONObject message = extractResponse(rawMessage); if (message == null) { return; } if (message.optInt("id", -1) != -1) { responses.add(message); return; } // not null, not a command response. // should be an event. Event e = EventFactory.createEvent(message); if (isPageLoad(message)) { listener.onPageLoad(); return; } if (isImportantDOMChange(e)) { listener.domHasChanged(e); } if ("Page.frameDetached".equals(message.optString("method"))) { listener.frameDied(message); return; } else { if (showIgnoredMessaged) { System.err.println(System.currentTimeMillis() + "\t" + message.toString()); } } } catch (Exception e) { e.printStackTrace(); } } private boolean isImportantDOMChange(Event e) { return (e instanceof ChildIframeInserted || e instanceof ChildNodeRemoved); } private boolean isPageLoad(JSONObject message) { String method = message.optString("method"); return "Page.loadEventFired".equals(method); // return "Profiler.resetProfiles".equals(method) || // "DOM.documentUpdated".equals(method); } private JSONObject extractResponse(String message) throws Exception { message = message.replace( "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">", ""); SAXReader reader = new SAXReader(); Document document = reader.read(IOUtils.toInputStream(message)); Node n = document.selectSingleNode("/plist/dict/dict/data"); if (n != null) { String encoded = n.getText(); byte[] bytes = Base64.decodeBase64(encoded); String s = new String(bytes); JSONObject o = new JSONObject(s); return o; } else { return null; } } @Override public JSONObject getResponse(int id) throws TimeoutException { long timeout = 5 * 1000; // TODO handle stop() in there long end = System.currentTimeMillis() + timeout; while (true) { if (System.currentTimeMillis() > end) { throw new TimeoutException("timeout waiting for a response for request id : " + id); } try { Thread.sleep(10); for (JSONObject o : responses) { if (o.optInt("id") == id) { // responses.remove(o); return o; } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void stop() { if (t != null) { t.interrupt(); } } }