package loon.html5.gwt.preloader;
import loon.LSystem;
import loon.html5.gwt.preloader.AssetFilter.AssetType;
import loon.utils.ObjectMap;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.typedarrays.shared.Int8Array;
import com.google.gwt.typedarrays.shared.TypedArrays;
import com.google.gwt.xhr.client.ReadyStateChangeHandler;
import com.google.gwt.xhr.client.XMLHttpRequest;
import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;
/** 流氓写法,做一个内部接口,将除了图片和音效外的资源,一律写在class里加载,这样就没有跨域问题了,就可以不必经过服务器,而在任意浏览器运行了…… **/
public class LocalAssetDownloader extends IDownloader {
private final LocalAssetResources localRes;
private boolean tryInline = false;
public LocalAssetDownloader(LocalAssetResources res) {
super();
this.localRes = res;
}
@SuppressWarnings("unchecked")
public void load(String url, AssetType type, String mimeType,
AssetLoaderListener<?> listener) {
switch (type) {
case Text:
loadText(url, (AssetLoaderListener<String>) listener);
break;
case Image:
loadImage(url, mimeType,
(AssetLoaderListener<ImageElement>) listener);
break;
case Binary:
loadBinary(url, (AssetLoaderListener<Blob>) listener);
break;
case Audio:
loadAudio(url, (AssetLoaderListener<Void>) listener);
break;
case Directory:
listener.onSuccess(null);
break;
default:
throw new RuntimeException("Unsupported asset type " + type);
}
}
public void loadText(String url, final AssetLoaderListener<String> listener) {
if (localRes == null) {
XMLHttpRequest request = XMLHttpRequest.create();
request.setOnReadyStateChange(new ReadyStateChangeHandler() {
@Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
if (xhr.getStatus() != 200) {
listener.onFailure();
} else {
listener.onSuccess(xhr.getResponseText());
}
}
}
});
setOnProgress(request, listener);
request.open("GET", url);
request.setRequestHeader("Content-Type",
"text/plain; charset=utf-8");
request.send();
return;
}
String path = url;
int pathLen;
do {
pathLen = path.length();
path = path.replaceAll("[^/]+/\\.\\./", "");
} while (path.length() != pathLen);
path = path.replace("\\", "/");
ObjectMap<String, String> res = localRes.texts;
String text = res.get(path);
if (text == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
text = res
.get(path.substring(path.indexOf('/') + 1, path.length()));
}
if (text == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
text = res.get(LSystem.getFileName(path));
}
if (text == null) {
text = res.get(LSystem.getFileName(path = ("assets/" + path)));
}
if (text == null) {
if (tryInline) {
XMLHttpRequest request = XMLHttpRequest.create();
request.setOnReadyStateChange(new ReadyStateChangeHandler() {
@Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
if (xhr.getStatus() != 200) {
listener.onFailure();
} else {
listener.onSuccess(xhr.getResponseText());
}
}
}
});
setOnProgress(request, listener);
request.open("GET", url);
request.setRequestHeader("Content-Type",
"text/plain; charset=utf-8");
request.send();
return;
} else {
listener.onFailure();
}
} else {
listener.onSuccess(text);
}
setOnProgress(listener);
}
public void loadBinary(final String url,
final AssetLoaderListener<Blob> listener) {
if (localRes == null) {
XMLHttpRequest request = XMLHttpRequest.create();
request.setOnReadyStateChange(new ReadyStateChangeHandler() {
@Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
if (xhr.getStatus() != 200) {
listener.onFailure();
} else {
Int8Array data = TypedArrays.createInt8Array(xhr
.getResponseArrayBuffer());
listener.onSuccess(new Blob(data));
}
}
}
});
setOnProgress(request, listener);
request.open("GET", url);
request.setResponseType(ResponseType.ArrayBuffer);
request.send();
return;
}
String path = url;
int pathLen;
do {
pathLen = path.length();
path = path.replaceAll("[^/]+/\\.\\./", "");
} while (path.length() != pathLen);
path = path.replace("\\", "/");
ObjectMap<String, Blob> res = localRes.binaries;
Blob blob = res.get(path);
if (blob == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
blob = res
.get(path.substring(path.indexOf('/') + 1, path.length()));
}
if (blob == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
blob = res.get(LSystem.getFileName(path));
}
if (blob == null) {
blob = res.get(LSystem.getFileName(path = ("assets/" + path)));
}
if (blob == null) {
if (tryInline) {
XMLHttpRequest request = XMLHttpRequest.create();
request.setOnReadyStateChange(new ReadyStateChangeHandler() {
@Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
if (xhr.getStatus() != 200) {
listener.onFailure();
} else {
Int8Array data = TypedArrays
.createInt8Array(xhr
.getResponseArrayBuffer());
listener.onSuccess(new Blob(data));
}
}
}
});
setOnProgress(request, listener);
request.open("GET", url);
request.setResponseType(ResponseType.ArrayBuffer);
request.send();
return;
} else {
listener.onFailure();
}
} else {
listener.onSuccess(blob);
}
setOnProgress(listener);
}
public void loadAudio(String url, final AssetLoaderListener<Void> listener) {
if (useBrowserCache) {
loadBinary(url, new AssetLoaderListener<Blob>() {
@Override
public void onProgress(double amount) {
listener.onProgress(amount);
}
@Override
public void onFailure() {
listener.onFailure();
}
@Override
public void onSuccess(Blob result) {
listener.onSuccess(null);
}
});
} else {
listener.onSuccess(null);
}
}
public void loadImage(final String url, final String mimeType,
final AssetLoaderListener<ImageElement> listener) {
String path = url;
int pathLen;
do {
pathLen = path.length();
path = path.replaceAll("[^/]+/\\.\\./", "");
} while (path.length() != pathLen);
path = path.replace("\\", "/");
if (tryInline) {
final ImageElement image = createImage();
hookImgListener(image, new ImgEventListener() {
@Override
public void onEvent(NativeEvent event) {
if (event.getType().equals("error")) {
listener.onFailure();
} else {
listener.onSuccess(image);
}
}
});
image.setSrc(url);
} else {
ObjectMap<String, String> res = localRes.images;
String base64 = res.get(path);
if (base64 == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
base64 = res.get(path.substring(path.indexOf('/') + 1,
path.length()));
}
if (base64 == null
&& (path.indexOf('\\') != -1 || path.indexOf('/') != -1)) {
base64 = res.get(LSystem.getFileName(path));
}
if (base64 == null) {
base64 = res
.get(LSystem.getFileName(path = ("assets/" + path)));
}
if (base64 == null) {
final ImageElement image = createImage();
hookImgListener(image, new ImgEventListener() {
@Override
public void onEvent(NativeEvent event) {
if (event.getType().equals("error")) {
listener.onFailure();
} else {
listener.onSuccess(image);
}
}
});
setOnProgress(listener);
image.setSrc(path);
return;
}
final ImageElement image = createImage();
hookImgListener(image, new ImgEventListener() {
@Override
public void onEvent(NativeEvent event) {
if (event.getType().equals("error")) {
listener.onFailure();
} else {
listener.onSuccess(image);
}
}
});
setOnProgress(listener);
image.setSrc("data:" + mimeType + ";base64," + base64);
}
}
public boolean isTryInline() {
return tryInline;
}
public void setTryInline(boolean tryInline) {
this.tryInline = tryInline;
}
@Override
public void clear() {
if (localRes != null) {
localRes.clear();
}
}
}