Java tutorial
/* Copyright (C) 2010 Copyright 2010 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.googlecode.gwtquake.client; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import com.google.gwt.core.client.Duration; import com.google.gwt.user.client.Timer; import com.google.gwt.xhr.client.ReadyStateChangeHandler; import com.google.gwt.xhr.client.XMLHttpRequest; import com.googlecode.gwtquake.shared.common.Com; import com.googlecode.gwtquake.shared.common.Compatibility; import com.googlecode.gwtquake.shared.common.ResourceLoader; import com.googlecode.gwtquake.shared.util.StringToByteBuffer; public class GwtResourceLoaderImpl implements ResourceLoader.Impl { private static final int RECEIVED_WAIT_TIME = 1; private int freeSequenceNumber; private int ignoreSequenceNumbersBelow; private int currentSequenceNumber; private ArrayList<ResponseHandler> readyList = new ArrayList<ResponseHandler>(); static class ResponseHandler { int sequenceNumber; ResourceLoader.Callback callback; String response; ResponseHandler(int sequenceNumber, ResourceLoader.Callback callback, String response) { this.sequenceNumber = sequenceNumber; this.callback = callback; this.response = response; } } private static StringToByteBuffer sbb = (StringToByteBuffer) (Object) ByteBuffer.allocate(1); public boolean pump() { return currentSequenceNumber != freeSequenceNumber; } public void reset() { ignoreSequenceNumbersBelow = freeSequenceNumber; currentSequenceNumber = freeSequenceNumber; } public void loadResourceAsync(final String path, final ResourceLoader.Callback callback) { XMLHttpRequest req = XMLHttpRequest.create(); final Exception e = new Exception(); final int mySequenceNumber = freeSequenceNumber++; req.setOnReadyStateChange(new ReadyStateChangeHandler() { boolean receivingMsg; public void onReadyStateChange(final XMLHttpRequest xhr) { if (xhr.getReadyState() == 3 && !receivingMsg) { Com.Printf("Receiving #" + mySequenceNumber + ": " + path + "\n"); receivingMsg = true; } else if (xhr.getReadyState() == 4) { if (mySequenceNumber < ignoreSequenceNumbersBelow) { Com.Printf("Ignoring outdated response #" + mySequenceNumber + ": " + path + "\n"); } else { String response; if (xhr.getStatus() != 200) { Com.Printf("Failed to load file #" + mySequenceNumber + ": " + path + " status: " + xhr.getStatus() + "/" + xhr.getStatusText() + "\n"); ResourceLoader.fail(new IOException("status = " + xhr.getStatus())); response = null; } else { response = xhr.getResponseText(); Com.Printf("Received response #" + mySequenceNumber + ": " + path + "\r"); } readyList.add(0, new ResponseHandler(mySequenceNumber, callback, response)); if (mySequenceNumber == currentSequenceNumber) { processReadyList(); } } } } }); Com.Printf("Requesting: " + path + "\n"); overrideMimeType(req, "text/plain; charset=x-user-defined"); req.open("GET", "/baseq2/" + path); req.send(); } private native void overrideMimeType(XMLHttpRequest req, String mimeType) /*-{ req.overrideMimeType(mimeType); }-*/; private void processReadyList() { new Timer() { @Override public void run() { for (int i = readyList.size() - 1; i >= 0; i--) { ResponseHandler handler = readyList.get(i); if (handler.sequenceNumber == currentSequenceNumber) { if (handler.response != null) { double t0 = Duration.currentTimeMillis(); handler.callback.onSuccess(sbb.stringToByteBuffer(handler.response)); Com.Printf("Processed #" + currentSequenceNumber + " in " + (Duration.currentTimeMillis() - t0) / 1000.0 + "s\r"); } readyList.remove(i); currentSequenceNumber++; processReadyList(); return; } } } }.schedule(RECEIVED_WAIT_TIME); } }