diff options
40 files changed, 1771 insertions, 362 deletions
diff --git a/gwtquery-core/pom.xml b/gwtquery-core/pom.xml index a90c6a82..6ccb811b 100644 --- a/gwtquery-core/pom.xml +++ b/gwtquery-core/pom.xml @@ -16,9 +16,16 @@ <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> - <type>jar</type> <scope>test</scope> </dependency> + <!-- Commented in order not to depend on it, but useful when we want test ajax CORS + <dependency> + <groupId>net.sourceforge.htmlunit</groupId> + <artifactId>htmlunit</artifactId> + <version>2.13</version> + <scope>test</scope> + </dependency> + --> <dependency> <groupId>com.google.gwt</groupId> <artifactId>gwt-user</artifactId> @@ -51,7 +58,7 @@ <directory>${basedir}/src/main/java</directory> </resource> <resource> - <directory>${basedir}/src/main/resources</directory> + <directory>${basedir}/src/main/super</directory> </resource> </resources> <testResources> diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml index 520ceaa0..5398aa58 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml +++ b/gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml @@ -17,6 +17,9 @@ <module> <inherits name='com.google.gwt.user.User'/> + <source path="client"/> + <super-source path="super"/> + <!-- Browser flags --> <generate-with class="com.google.gwt.query.rebind.BrowserGenerator"> <when-type-assignable class="com.google.gwt.query.client.Browser"/> @@ -36,6 +39,9 @@ <generate-with class="com.google.gwt.query.rebind.JsonBuilderGenerator"> <when-type-assignable class="com.google.gwt.query.client.builders.JsonBuilder"/> </generate-with> + <generate-with class="com.google.gwt.query.rebind.JsonBuilderGenerator"> + <when-type-assignable class="com.google.gwt.query.client.builders.JsonFactory"/> + </generate-with> <generate-with class="com.google.gwt.query.rebind.XmlBuilderGenerator"> <when-type-assignable class="com.google.gwt.query.client.builders.XmlBuilder"/> </generate-with> diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml b/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml index 6453aba3..f3e2e72a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml +++ b/gwtquery-core/src/main/java/com/google/gwt/query/QueryMin.gwt.xml @@ -22,7 +22,10 @@ <!-- Inherit GQuery module --> <inherits name='com.google.gwt.query.Query'/> - + + <source path="client"/> + <super-source path="super"/> + <!-- Detect whether querySelectorAll is available --> <define-property name="selectorCapability" values="native,js"/> <property-provider name="selectorCapability"> @@ -42,21 +45,6 @@ </any> </set-property> - <!-- JSNI Generator --> - <generate-with class="com.google.gwt.query.rebind.JsniBundleGenerator"> - <when-type-assignable class="com.google.gwt.query.client.builders.JsniBundle"/> - </generate-with> - - <!-- Browser flags --> - <generate-with class="com.google.gwt.query.rebind.BrowserGenerator"> - <when-type-assignable class="com.google.gwt.query.client.Browser"/> - </generate-with> - - <!-- GQuery.console --> - <replace-with class="com.google.gwt.query.client.impl.ConsoleBrowser"> - <when-type-assignable class="com.google.gwt.query.client.Console"/> - </replace-with> - <!-- Selector Engines --> <replace-with class="com.google.gwt.query.client.impl.SelectorEngineNativeMin"> <when-type-assignable class="com.google.gwt.query.client.impl.SelectorEngineImpl"/> diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Binder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Binder.java new file mode 100644 index 00000000..2f0e47e5 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Binder.java @@ -0,0 +1,82 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client; + +import com.google.gwt.query.client.builders.JsonBuilder; + + +/** + * Interface using for Data Binders valid for JVM and JS. + */ +public interface Binder { + /** + * load a properties object. + */ + <J> J load(Object prp); + + /** + * parses a json string and loads the resulting properties object. + */ + <J> J parse(String json); + + /** + * Returns the underlying object, normally a Properties jso in client + * and a Json implementation in JVM. + */ + <J> J getBound(); + + /** + * Return the Object with the given key. + */ + <T> T get(Object key); + + /** + * Set an Object with the given key. + */ + <T> T set(Object key, Object val); + + /** + * return a list of field names. + */ + String[] getFieldNames(); + + /** + * return a json string which represents the object. + * Example {"name":"manolo","surname":"carrasco"} + */ + String toJson(); + + /** + * return a string which represents the object with an alias for the + * className useful for serialization. + * + * Example {"user":{"name":"manolo","surname":"carrasco"}} + */ + String toJsonWithName(); + + /** + * return a string which represents the object in a queryString format. + */ + String toQueryString(); + + /** + * return the name for this type + */ + String getJsonName(); + + + <T extends JsonBuilder> T as (Class<T> clz); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java new file mode 100644 index 00000000..27dbbe78 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.JsonFactory; +import com.google.gwt.query.client.plugins.ajax.Ajax.AjaxTransport; +import com.google.gwt.query.client.plugins.ajax.AjaxTransportJs; +import com.google.gwt.query.vm.AjaxTransportJre; +import com.google.gwt.query.vm.JsonFactoryJre; + +public abstract class GQ { + + private static JsonFactory jsonFactory; + private static AjaxTransport ajaxTransport; + + public static <T extends JsonBuilder> T create(Class<T> clz) { + return getFactory().create(clz); + } + + public static <T extends JsonBuilder> T create(Class<T> clz, String payload) { + T ret = create(clz); + ret.load(payload); + return ret; + } + + public static <T extends JsonBuilder> T create(Class<T> clz, Binder obj) { + T ret = create(clz); + ret.load(obj.getBound()); + return ret; + } + + public static Binder create(String s) { + return getFactory().create(s); + } + + public static Binder create() { + return getFactory().create(); + } + + public static AjaxTransport getAjaxTransport() { + if (ajaxTransport == null) { + ajaxTransport = GWT.isClient() ? + new AjaxTransportJs() : + new AjaxTransportJre(); + } + return ajaxTransport; + } + + private static JsonFactory getFactory() { + if (jsonFactory == null) { + jsonFactory = GWT.isClient() ? + GWT.<JsonFactory>create(JsonFactory.class) : + new JsonFactoryJre(); + } + return jsonFactory; + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java index 3d31e852..60ac6a6b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java @@ -15,16 +15,17 @@ */ package com.google.gwt.query.client; +import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayMixed; -import com.google.gwt.core.client.GWT; +import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.js.JsCache; import com.google.gwt.query.client.js.JsUtils; /** * JSO for accessing Javascript objective literals used by GwtQuery functions. */ -public class Properties extends JavaScriptObject { +public class Properties extends JavaScriptObject implements Binder { public static Properties create() { return JsCache.create().cast(); @@ -179,8 +180,10 @@ public class Properties extends JavaScriptObject { this[name].__f = f; }-*/; - public final <T, O> void set(T name, O val) { + @SuppressWarnings("unchecked") + public final Properties set(Object name, Object val) { c().put(String.valueOf(name), val); + return this; } public final String tostring() { @@ -199,4 +202,42 @@ public class Properties extends JavaScriptObject { return c().length() == 0; } + public final <J> J load(Object prp) { + c().clear(); + if (prp instanceof JsCache) { + c().copy((JsCache)prp); + } + return getBound(); + } + + public final <J> J parse(String json) { + return load(JsUtils.parseJSON(json)); + } + + public final String[] getFieldNames() { + return c().keys(); + } + + public final String toJson() { + return toJsonString(); + } + + public final String toJsonWithName() { + return "{\"properties\":{" + toJson() + "}"; + } + + @SuppressWarnings("unchecked") + public final <J> J getBound() { + return (J)this; + } + + public final String getJsonName() { + return "jso"; + } + + public final <T extends JsonBuilder> T as(Class<T> clz) { + T ret = GQ.create(clz); + ret.load(this); + return ret; + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java index 41a7171c..6e6d6f3a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java @@ -15,22 +15,13 @@ */ package com.google.gwt.query.client.builders; -import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.Binder; + /** * Tagging interface used to generate JsonBuilder classes. */ -public interface JsonBuilder { - - /** - * load a properties object. - */ - <J> J load(Object prp); - - /** - * parses a json string and loads the resulting properties object. - */ - <J> J parse(String json); +public interface JsonBuilder extends Binder { /** * parses a json string and loads the resulting properties object, @@ -40,22 +31,14 @@ public interface JsonBuilder { <J> J parse(String json, boolean fix); /** - * Returns the javascript properties object. - */ - Properties getProperties(); - - /** - * return a list of field names. - */ - String[] getFieldNames(); - - /** - * return a string which represents the object with an alias for the className + * Returns the wrapped object, normally a Properties jso in client + * but can be used to return the underlying Json implementation in JVM + * @deprecated use asObject() instead */ - String toJson(); + <J> J getProperties(); /** - * return the Json name for this class + * return the short name of this class, to use in json structures. */ String getJsonName(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java index e0d48c26..40dbdae7 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java @@ -17,6 +17,7 @@ package com.google.gwt.query.client.builders; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.Properties; import com.google.gwt.query.client.js.JsObjectArray; import com.google.gwt.query.client.js.JsUtils; @@ -26,16 +27,19 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J protected Properties p = Properties.create(); @SuppressWarnings("unchecked") + @Override public J parse(String json) { return load(JsUtils.parseJSON(json)); } @SuppressWarnings("unchecked") + @Override public J parse(String json, boolean fix) { return fix ? parse(Properties.wrapPropertiesString(json)) : parse(json); } @SuppressWarnings("unchecked") + @Override public J load(Object prp) { assert prp == null || prp instanceof JavaScriptObject || prp instanceof String; if (prp != null && prp instanceof String) { @@ -51,7 +55,7 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J if (r.length > 0 && r[0] instanceof JsonBuilder) { JsArray<JavaScriptObject> a = JavaScriptObject.createArray().cast(); for (T o : r) { - a.push(((JsonBuilder)o).getProperties()); + a.push(((JsonBuilder)o).<Properties>getBound()); } p.set(n, a); } else { @@ -88,8 +92,47 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J return p.tostring(); } + @Override + public String toJson() { + return p.tostring(); + } + + public String toJsonWithName() { + return "{\"" + getJsonName() + "\":" + p.tostring() + "}"; + } + + @SuppressWarnings("unchecked") + @Override public Properties getProperties() { return p; } - + + @Override + public String toQueryString() { + return p.toQueryString(); + } + + @SuppressWarnings("unchecked") + @Override + public Properties getBound() { + return p; + } + + public <T> T get(Object key) { + return p.get(key); + } + + @SuppressWarnings("unchecked") + public <T> T set(Object key, Object val) { + if (val instanceof Binder) { + p.set(key, ((Binder)val).getBound()); + } else { + p.set(key, val); + } + return (T)this; + } + + public <T extends JsonBuilder> T as(Class<T> clz) { + return p.as(clz); + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonFactory.java new file mode 100644 index 00000000..4bc57c9c --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonFactory.java @@ -0,0 +1,9 @@ +package com.google.gwt.query.client.builders; + +import com.google.gwt.query.client.Binder; + +public interface JsonFactory { + <T extends JsonBuilder> T create(Class<T> clz); + Binder create(String s); + Binder create(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java index c8f00a6c..f10d998b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java @@ -36,6 +36,12 @@ public class JsCache extends JavaScriptObject { if (ary) this.concat(ary); }-*/; + public final void copy(JsCache jso) { + for (String k : jso.keys()) { + put(k, jso.get(k)); + } + } + public final void pushAll(JavaScriptObject prevElem) { checkNull(); JsCache c = prevElem.cast(); @@ -47,14 +53,12 @@ public class JsCache extends JavaScriptObject { public final native void delete(Object name) /*-{ delete this[name]; }-*/; - - public final native <T> void clear() /*-{ - if (this.length) { - for (i = this.length - 1; i >= 0; i--) - delete this[i]; - this.length = 0; + + public final void clear() { + for (String k : keys()) { + delete(k); } - }-*/; + } public final native boolean exists(Object name) /*-{ return !!this[name]; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java index be06f79b..ac01f7ca 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java @@ -531,7 +531,7 @@ public class JsUtils { } else { Properties p = prop.getJavaScriptObject(k); if (p != null) { - ret += p.toQueryString(); + ret += k + "=" + p.tostring(); } else { String v = prop.getStr(k); if (v != null && !v.isEmpty() && !"null".equalsIgnoreCase(v)) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java index c7b66d5b..7f6ce927 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java @@ -166,7 +166,8 @@ public class Effects extends QueuePlugin<Effects> { public Effects animate(Object stringOrProperties, int duration, Easing easing, Function... funcs) { final Properties p = (stringOrProperties instanceof String) - ? $$((String) stringOrProperties) : (Properties) stringOrProperties; + ? (Properties) $$((String) stringOrProperties) + : (Properties) stringOrProperties; if (p.getStr("duration") != null) { duration = p.getInt("duration"); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java index 3170c3cb..9df0f582 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/Ajax.java @@ -1,21 +1,20 @@ package com.google.gwt.query.client.plugins.ajax; -import com.google.gwt.core.client.Callback; import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.ScriptInjector; import com.google.gwt.dom.client.Element; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.Response; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQ; import com.google.gwt.query.client.GQuery; import com.google.gwt.query.client.Promise; import com.google.gwt.query.client.Properties; import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.Plugin; -import com.google.gwt.query.client.plugins.deferred.PromiseFunction; -import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilder; -import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilderJSONP; /** * Ajax class for GQuery. @@ -33,17 +32,27 @@ import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilderJSONP; */ public class Ajax extends GQuery { + public static interface AjaxTransport { + Promise getJsonP(Settings settings); + + Promise getLoadScript(Settings settings); + + Promise getXhr(Settings settings); + } + + static AjaxTransport transport = GQ.getAjaxTransport(); + /** * Ajax Settings object */ public interface Settings extends JsonBuilder { String getContentType(); Element getContext(); - Properties getData(); + Binder getData(); String getDataString(); String getDataType(); Function getError(); - Properties getHeaders(); + Binder getHeaders(); String getPassword(); Function getSuccess(); int getTimeout(); @@ -52,11 +61,11 @@ public class Ajax extends GQuery { String getUsername(); Settings setContentType(String t); Settings setContext(Element e); - Settings setData(Properties p); + Settings setData(Object p); Settings setDataString(String d); Settings setDataType(String t); Settings setError(Function f); - Settings setHeaders(Properties p); + Settings setHeaders(Binder p); Settings setPassword(String p); Settings setSuccess(Function f); Settings setTimeout(int t); @@ -105,7 +114,8 @@ public class Ajax extends GQuery { * @param settings a Properties object with the configuration of the Ajax request. */ public static Promise ajax(Settings settings) { - + resolveSettings(settings); + final Function onSuccess = settings.getSuccess(); if (onSuccess != null) { onSuccess.setElement(settings.getContext()); @@ -116,29 +126,26 @@ public class Ajax extends GQuery { onError.setElement(settings.getContext()); } - String httpMethod = settings.getType() == null ? "POST" : settings.getType().toUpperCase(); - Object data = resolveData(settings, httpMethod); - final String url = resolveUrl(settings, httpMethod, data); final String dataType = settings.getDataType(); Promise ret = null; if ("jsonp".equalsIgnoreCase(dataType)) { - ret = new PromiseReqBuilderJSONP(url, null, settings.getTimeout()); + ret = transport.getJsonP(settings); } else if ("loadscript".equalsIgnoreCase(dataType)){ - ret = createPromiseScriptInjector(url); + ret = transport.getLoadScript(settings); } else { - ret = new PromiseReqBuilder(settings, httpMethod, url, data) + ret = transport.getXhr(settings) .then(new Function() { public Object f(Object...args) { - Response response = (Response)args[0]; - Request request = (Request)args[1]; - Object retData = null; + Response response = arguments(0); + Request request = arguments(1); + Object retData = response.getText(); try { if ("xml".equalsIgnoreCase(dataType)) { retData = JsUtils.parseXML(response.getText()); } else if ("json".equalsIgnoreCase(dataType)) { - retData = JsUtils.parseJSON(response.getText()); + retData = GQ.create(response.getText()); } else { retData = response.getText(); if ("script".equalsIgnoreCase(dataType)) { @@ -146,17 +153,20 @@ public class Ajax extends GQuery { } } } catch (Exception e) { - if (GWT.getUncaughtExceptionHandler() != null) { + if (GWT.isClient() && GWT.getUncaughtExceptionHandler() != null) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); + } else { + e.printStackTrace(); } } return new Object[]{retData, "success", request, response}; } }, new Function() { public Object f(Object...args) { - Throwable exception = (Throwable)args[0]; - Request request = (Request)args[1]; - return new Object[]{null, exception.getMessage(), request, null, exception}; + Throwable exception = getArgument(0, Throwable.class); + Request request = getArgument(0, Request.class); + String msg = String.valueOf(exception); + return new Object[]{null, msg, request, null, exception}; } }); } @@ -169,50 +179,36 @@ public class Ajax extends GQuery { return ret; } - - private static Promise createPromiseScriptInjector(final String url) { - return new PromiseFunction() { - public void f(final Deferred dfd) { - ScriptInjector.fromUrl(url).setWindow(window) - .setCallback(new Callback<Void, Exception>() { - public void onSuccess(Void result) { - dfd.resolve(); - } - public void onFailure(Exception reason) { - dfd.reject(reason); - } - }).inject(); - } - }; - } - - private static String resolveUrl(Settings settings, String httpMethod, Object data) { + private static void resolveSettings(Settings settings) { String url = settings.getUrl(); - assert url != null : "no url found in settings"; - if ("GET".equals(httpMethod) && data instanceof String) { - url += (url.contains("?") ? "&" : "?") + data; + assert settings != null && settings.getUrl() != null: "no url found in settings"; + + String type = "POST"; + if (settings.getType() != null) { + type = settings.getType().toUpperCase(); } - return url; - } - - private static Object resolveData(Settings settings, String httpMethod) { - Object data = settings.getDataString(); - Properties sdata = settings.getData(); - if (data == null && sdata != null) { - String type = settings.getDataType(); - if (type != null - && (httpMethod.matches("(POST|PUT)")) - && type.equalsIgnoreCase("json")) { - data = sdata.toJsonString(); - } else if (JsUtils.isFormData(sdata)) { - data = sdata; + if ("jsonp".equalsIgnoreCase(settings.getDataType())) { + type = "GET"; + } + settings.setType(type); + + Binder data = settings.getData(); + if (data != null) { + if (data.getBound() instanceof JavaScriptObject && JsUtils.isFormData(data.<JavaScriptObject>getBound())) { + settings.setDataString(null); + } else if (settings.getType().matches("(POST|PUT)") && "json".equalsIgnoreCase(settings.getDataType())) { + settings.setDataString(data.toJson()); } else { - data = sdata.toQueryString(); + settings.setDataString(data.toQueryString()); } } - return data; - } + if ("GET".equals(settings.getType()) && settings.getDataString() != null) { + url += (url.contains("?") ? "&" : "?") + settings.getDataString(); + settings.setUrl(url); + } + } + public static Promise ajax(String url, Function onSuccess, Function onError) { return ajax(url, onSuccess, onError, (Settings) null); } @@ -237,16 +233,19 @@ public class Ajax extends GQuery { } public static Settings createSettings() { - return createSettings($$("")); + return createSettings(""); } public static Settings createSettings(String prop) { - return createSettings($$(prop)); + Settings s = GQ.create(Settings.class); + if (prop != null && !prop.isEmpty()) + s.parse(prop); + return s; } - public static Settings createSettings(Properties p) { - Settings s = GWT.create(Settings.class); - s.load(p); + public static Settings createSettings(Binder p) { + Settings s = GQ.create(Settings.class); + s.load(p.getBound()); return s; } @@ -326,7 +325,7 @@ public class Ajax extends GQuery { .setSuccess(success) ); } - + public static Promise post(String url, Properties data) { return post(url, data, null); } @@ -363,7 +362,7 @@ public class Ajax extends GQuery { // Note: using '\s\S' instead of '.' because gwt String emulation does // not support java embedded flag expressions (?s) and javascript does // not have multidot flag. - String s = getArguments()[0].toString().replaceAll("<![^>]+>\\s*", "") + String s = arguments(0).toString().replaceAll("<![^>]+>\\s*", "") .replaceAll("</?html[\\s\\S]*?>\\s*", "") .replaceAll("<head[\\s\\S]*?</head>\\s*", "") .replaceAll("<script[\\s\\S]*?</script>\\s*", "") diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/AjaxTransportJs.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/AjaxTransportJs.java new file mode 100644 index 00000000..fe4e91b8 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/AjaxTransportJs.java @@ -0,0 +1,52 @@ +package com.google.gwt.query.client.plugins.ajax; + +import com.google.gwt.core.client.Callback; +import com.google.gwt.core.client.ScriptInjector; +import com.google.gwt.dom.client.ScriptElement; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Promise; +import com.google.gwt.query.client.plugins.ajax.Ajax.AjaxTransport; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; +import com.google.gwt.query.client.plugins.deferred.Deferred.DeferredPromiseImpl; +import com.google.gwt.query.client.plugins.deferred.PromiseFunction; +import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilder; +import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilderJSONP; + +/** + * Ajax transport for Client side. + */ +public class AjaxTransportJs implements AjaxTransport { + + @Override + public Promise getJsonP(Settings settings) { + return new PromiseReqBuilderJSONP(settings.getUrl(), settings.getTimeout()); + } + + @Override + public Promise getLoadScript(final Settings settings) { + return new PromiseFunction() { + private ScriptElement scriptElement; + public void f(final Deferred dfd) { + scriptElement = ScriptInjector.fromUrl(settings.getUrl()).setWindow(GQuery.window) + .setCallback(new Callback<Void, Exception>() { + public void onSuccess(Void result) { + GQuery.$(GQuery.window).delay(0, new Function(){ + public void f() { + dfd.resolve(scriptElement); + } + }); + } + public void onFailure(Exception reason) { + dfd.reject(reason); + } + }).inject().cast(); + } + }; + } + + public Promise getXhr(Settings settings) { + return new PromiseReqBuilder(settings); + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java index 61273296..e6bc6d63 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/PromiseReqBuilder.java @@ -21,8 +21,8 @@ import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.RequestPermissionException; import com.google.gwt.http.client.Response; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.Function; -import com.google.gwt.query.client.Properties; import com.google.gwt.query.client.js.JsCache; import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; @@ -64,7 +64,13 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal * which are not available in GWT, like adding progress handles or sending * javascript data (like forms in modern html5 file api) */ - public PromiseReqBuilder(Settings settings, String httpMethod, String url, Object data) { + public PromiseReqBuilder(Settings settings) { + String httpMethod = settings.getType(); + String url = settings.getUrl(); + Binder data = settings.getData(); + String ctype = settings.getContentType(); + Boolean isFormData = data != null && data.getBound() instanceof JavaScriptObject && JsUtils.isFormData(data.<JavaScriptObject>getBound()); + XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create(); try { if (settings.getUsername() != null && settings.getPassword() != null) { @@ -86,7 +92,7 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal JsCache p = arguments(0); double total = p.getDouble("total"); double loaded = p.getDouble("loaded"); - double percent = 100 * loaded / total; + double percent = loaded == 0 ? 0 : total == 0 ? 100 : (100 * loaded / total); dfd.notify(total, loaded, percent, "download"); } })); @@ -102,24 +108,19 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal } })); - Properties headers = settings.getHeaders(); + Binder headers = settings.getHeaders(); if (headers != null) { - for (String headerKey : headers.keys()) { - xmlHttpRequest.setRequestHeader(headerKey, headers.getStr(headerKey)); + for (String headerKey : headers.getFieldNames()) { + xmlHttpRequest.setRequestHeader(headerKey, String.valueOf(headers.get(headerKey))); } } - if (data != null && !"GET".equalsIgnoreCase(httpMethod)) { - String ctype = settings.getContentType(); - if (data instanceof JavaScriptObject && JsUtils.isFormData((JavaScriptObject)data)) { - ctype = FormPanel.ENCODING_MULTIPART;; - } else if (ctype == null) { - String type = settings.getDataType(); - if (type != null && type.toLowerCase().startsWith("json")) { - ctype = "application/json; charset=utf-8"; - } else { - ctype = FormPanel.ENCODING_URLENCODED; - } + if (data != null && !isFormData && !"GET".equalsIgnoreCase(httpMethod)) { + String type = settings.getDataType(); + if (type != null && type.toLowerCase().startsWith("json")) { + ctype = "application/json; charset=utf-8"; + } else { + ctype = FormPanel.ENCODING_URLENCODED; } xmlHttpRequest.setRequestHeader("Content-Type", ctype); } @@ -129,6 +130,7 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal JsUtils.prop(xmlHttpRequest, "withCredentials", true); final Request request = createRequestVltr(xmlHttpRequest, settings.getTimeout(), this); + System.out.println("REQ timeout " + settings.getTimeout()); xmlHttpRequest.setOnReadyStateChange(new ReadyStateChangeHandler() { public void onReadyStateChange(XMLHttpRequest xhr) { @@ -140,7 +142,7 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal }); try { - JsUtils.runJavascriptFunction(xmlHttpRequest, "send", data); + JsUtils.runJavascriptFunction(xmlHttpRequest, "send", isFormData ? data.getBound() : settings.getDataString()); } catch (JavaScriptException e) { onError(null, e); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java index 57403501..ac9581cd 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java @@ -311,7 +311,7 @@ public class Transitions extends GQuery { } final Properties cssProps = (stringOrProperties instanceof String) - ? $$((String) stringOrProperties) + ? (Properties) $$((String) stringOrProperties) : (Properties) stringOrProperties; final String ease = easing == null ? "ease" : easing.toString(); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java index 51543454..3fc7868c 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java @@ -15,10 +15,19 @@ */ package com.google.gwt.query.rebind; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.ext.Generator; import com.google.gwt.core.ext.GeneratorContext; import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JArrayType; import com.google.gwt.core.ext.typeinfo.JClassType; @@ -29,27 +38,27 @@ import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.JsonBuilderBase; +import com.google.gwt.query.client.builders.JsonFactory; import com.google.gwt.query.client.builders.Name; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - /** */ public class JsonBuilderGenerator extends Generator { static JClassType functionType; static JClassType jsonBuilderType; + static JClassType settingsType; static JClassType jsType; static JClassType listType; static JClassType stringType; + static JClassType jsonFactoryType; + + public static String capitalize(String s) { if (s.length() == 0) return s; @@ -70,39 +79,49 @@ public class JsonBuilderGenerator extends Generator { public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, String requestedClass) throws UnableToCompleteException { + oracle = generatorContext.getTypeOracle(); JClassType clazz = oracle.findType(requestedClass); + jsonBuilderType = oracle.findType(JsonBuilder.class.getName()); + settingsType = oracle.findType(Binder.class.getName()); stringType = oracle.findType(String.class.getName()); jsType = oracle.findType(JavaScriptObject.class.getName()); listType = oracle.findType(List.class.getName()); functionType = oracle.findType(Function.class.getName()); + jsonFactoryType = oracle.findType(JsonFactory.class.getName()); String t[] = generateClassName(clazz); - SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0], t[1], - requestedClass); + boolean isFactory = clazz.isAssignableTo(jsonFactoryType); + + SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0], t[1], isFactory, requestedClass); if (sw != null) { - Set<String> attrs = new HashSet<String>(); - for (JMethod method : clazz.getInheritableMethods()) { - String methName = method.getName(); - //skip method from JsonBuilder - if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null){ - continue; - } + if (isFactory) { + generateCreateMethod(sw, treeLogger); + } else { + Set<String> attrs = new HashSet<String>(); + for (JMethod method : clazz.getInheritableMethods()) { + String methName = method.getName(); + //skip method from JsonBuilder + if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null || + settingsType.findMethod(method.getName(), method.getParameterTypes()) != null ) { + continue; + } - Name nameAnnotation = method.getAnnotation(Name.class); - String name = nameAnnotation != null - ? nameAnnotation.value() - : methName.replaceFirst("^(get|set)", ""); - if (nameAnnotation == null) { - name = name.substring(0, 1).toLowerCase() + name.substring(1); + Name nameAnnotation = method.getAnnotation(Name.class); + String name = nameAnnotation != null + ? nameAnnotation.value() + : methName.replaceFirst("^(get|set)", ""); + if (nameAnnotation == null) { + name = name.substring(0, 1).toLowerCase() + name.substring(1); + } + attrs.add(name); + generateMethod(sw, method, name, treeLogger); } - attrs.add(name); - generateMethod(sw, method, name, treeLogger); + generateFieldNamesMethod(sw, attrs, treeLogger); + generateToJsonMethod(sw, t[3], treeLogger); } - generateFieldNamesMethod(sw, attrs, treeLogger); - generateToJsonMethod(sw, t[3], treeLogger); sw.commit(treeLogger); } return t[2]; @@ -165,6 +184,9 @@ public class JsonBuilderGenerator extends Generator { String q = method.getReturnType().getQualifiedSourceName(); sw.println("return " + "((" + q + ")GWT.create(" + q + ".class))" + ".load(p.getJavaScriptObject(\"" + name + "\"));"); + } else if (isTypeAssignableTo(method.getReturnType(), settingsType)) { + String q = method.getReturnType().getQualifiedSourceName(); + sw.println("return " + "((" + q + ")p.getJavaScriptObject(\"" + name + "\"));"); } else if (retType.equals(Properties.class.getName())) { sw.println("return getPropertiesBase(\"" + name + "\");"); } else if (isTypeAssignableTo(method.getReturnType(), jsType)) { @@ -199,8 +221,8 @@ public class JsonBuilderGenerator extends Generator { sw.println("return Arrays.asList(" + ret + ");"); } } else if (method.getReturnType().isEnum() != null){ - sw.println("return "+method.getReturnType().getQualifiedSourceName()+".valueOf(p.getStr(\"" + name + "\"));"); - }else { + sw.println("return "+ method.getReturnType().getQualifiedSourceName() + ".valueOf(p.getStr(\"" + name + "\"));"); + } else { sw.println("System.err.println(\"JsonBuilderGenerator WARN: unknown return type " + retType + " " + ifaceName + "." + name + "()\"); "); // We return the object because probably the user knows how to handle it @@ -234,7 +256,7 @@ public class JsonBuilderGenerator extends Generator { } else if (type.isEnum() != null){ sw.println("p.set(\"" + name + "\", a.name());"); }else { - sw.println("p.set(\"" + name + "\", a);"); + sw.println("set(\"" + name + "\", a);"); } if (!"void".equals(retType)) { if (isTypeAssignableTo(method.getReturnType(), @@ -251,11 +273,10 @@ public class JsonBuilderGenerator extends Generator { public void generateToJsonMethod(SourceWriter sw, String name, TreeLogger logger) { sw.println("public final String getJsonName() {return \"" + name + "\";}"); - sw.println("public final String toJson() {return \"{\\\"\" + getJsonName() + \"\\\":\" + toString() + \"}\";}"); } protected SourceWriter getSourceWriter(TreeLogger logger, - GeneratorContext context, String packageName, String className, + GeneratorContext context, String packageName, String className, boolean isFactory, String... interfaceNames) { PrintWriter printWriter = context.tryCreate(logger, packageName, className); if (printWriter == null) { @@ -263,8 +284,10 @@ public class JsonBuilderGenerator extends Generator { } ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory( packageName, className); - composerFactory.setSuperclass("com.google.gwt.query.client.builders.JsonBuilderBase<" - + packageName + "." + className + ">"); + if (!isFactory) { + composerFactory.setSuperclass(JsonBuilderBase.class.getName() + + "<" + packageName + "." + className + ">"); + } composerFactory.addImport("com.google.gwt.query.client.js.*"); composerFactory.addImport("com.google.gwt.query.client.*"); composerFactory.addImport("com.google.gwt.core.client.*"); @@ -281,4 +304,33 @@ public class JsonBuilderGenerator extends Generator { JClassType c = t.isClassOrInterface(); return (c != null && c.isAssignableTo(o)); } + + private void generateCreateMethod(SourceWriter sw, TreeLogger logger) { + sw.println("public <T extends " + JsonBuilder.class.getName() + "> T create(Class<T> clz) {"); + sw.indent(); + ArrayList<JClassType> types = new ArrayList<JClassType>(); + for (JClassType t : oracle.getTypes()) { + if (t.isInterface() != null && t.isAssignableTo(jsonBuilderType) ) { + if (t.isPublic()) { + sw.println("if (clz == " + t.getQualifiedSourceName() + ".class) return GWT.<T>create(" + t.getQualifiedSourceName() + ".class);"); + } else { + logger.log(Type.WARN, t.getQualifiedSourceName() + " is not public"); + } + types.add(t); + } + } + sw.println("return null;"); + sw.outdent(); + sw.println("}"); + sw.println("public Binder create(String s) {"); + sw.indent(); + sw.println("return " + Properties.class.getName() + ".create(s);"); + sw.outdent(); + sw.println("}"); + sw.println("public Binder create() {"); + sw.indent(); + sw.println("return " + Properties.class.getName() + ".create();"); + sw.outdent(); + sw.println("}"); + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/vm/AjaxTransportJre.java b/gwtquery-core/src/main/java/com/google/gwt/query/vm/AjaxTransportJre.java new file mode 100644 index 00000000..0725465f --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/AjaxTransportJre.java @@ -0,0 +1,160 @@ +package com.google.gwt.query.vm; + +// import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.Response; +import com.google.gwt.query.client.Binder; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQ; +import com.google.gwt.query.client.GQuery; +import com.google.gwt.query.client.Promise; +import com.google.gwt.query.client.plugins.ajax.Ajax.AjaxTransport; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; +import com.google.gwt.query.client.plugins.deferred.PromiseFunction; +import com.google.gwt.user.server.Base64Utils; + +/** + * + */ +public class AjaxTransportJre implements AjaxTransport { + + private static String localDomain = null; + + public static void enableCORS(String domain) { + localDomain = domain; + System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); + } + + private final String USER_AGENT = "Mozilla/5.0"; + private final String jsonpCbRexp = "(?ms)^.*jre_callback\\((.*)\\).*$"; + + public Promise getJsonP(final Settings settings) { + String url = settings.getUrl().replaceFirst("callback=[^&]*", ""); + url += (url.contains("?") ? "&" : "?") + "callback=jre_callback"; + settings.setUrl(url); + + if (settings.getTimeout() < 1) { + settings.setTimeout(10000); + } + + return getXhr(settings, false) + .then(new Function() { + public Object f(Object... args) { + Response response = arguments(0); + if (response.getText().matches(jsonpCbRexp)) { + return GQ.create(response.getText().replaceFirst(jsonpCbRexp, "$1")); + } else { + return GQuery.Deferred().reject().promise(); + } + } + }); + } + + public Promise getLoadScript(Settings settings) { + return getXhr(settings, false); + } + + public Promise getXhr(final Settings settings) { + return getXhr(settings, true); + } + + private Promise getXhr(final Settings settings, final boolean cors) { + return new PromiseFunction() { + public void f(Deferred dfd) { + try { + Response response = httpClient(settings, cors); + int status = response.getStatusCode(); + if (status <= 0 || status >= 400) { + String statusText = status <= 0 ? "Bad CORS" : response.getStatusText(); + dfd.reject(null, new RequestException("HTTP ERROR: " + status + " " + statusText + "\n" + response.getText())); + } else { + dfd.resolve(response, null); + } + } catch (Exception e) { + dfd.reject(e, null); + } + } + }; + } + + private Response httpClient(Settings s, boolean cors) throws Exception { + String url = s.getUrl(); + assert url.toLowerCase().startsWith("http"); + + URL u = new URL(url); + HttpURLConnection c = (HttpURLConnection) u.openConnection(); + c.setRequestMethod(s.getType()); + c.setRequestProperty("User-Agent", USER_AGENT); + if (s.getUsername() != null && s.getPassword() != null) { + c.setRequestProperty ("Authorization", "Basic " + Base64Utils.toBase64((s.getUsername() + ":" + s.getPassword()).getBytes())); + } + + boolean isCORS = cors && localDomain != null && !s.getUrl().contains(localDomain); + if (isCORS) { + // TODO: fetch options previously to the request + // >> OPTIONS + // Origin: http://127.0.0.1:8888 + // Access-Control-Allow-Origin: http://127.0.0.1:8888 + // Access-Control-Allow-Credentials: true + // Access-Control-Request-Headers: content-type + // Access-Control-Allow-Headers + // Access-Control-Request-Method + // Access-Control-Allow-Methods: POST, GET + // Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS + + // >> POST/GET + // Origin: http://127.0.0.1:8888 + // Access-Control-Allow-Origin: http://127.0.0.1:8888 + // Access-Control-Allow-Credentials: true + c.setRequestProperty("Origin", localDomain); + } + + if (s.getTimeout() > 0) { + c.setConnectTimeout(s.getTimeout()); + c.setReadTimeout(s.getTimeout()); + } + + Binder headers = s.getHeaders(); + if (headers != null) { + for (String h : headers.getFieldNames()) { + c.setRequestProperty(h, "" + headers.get(h)); + } + } + + if (s.getType().matches("POST|PUT")) { + String ctype = s.getDataType(); + if (s.getDataType().toLowerCase().startsWith("json")) { + ctype = "application/json; charset=utf-8"; + } + c.setRequestProperty("Content-Type", ctype); + + c.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(c.getOutputStream()); + wr.writeBytes(s.getDataString()); + wr.flush(); + wr.close(); + } + + int code = c.getResponseCode(); + if (isCORS && !localDomain.equals(c.getHeaderField("Access-Control-Allow-Origin"))) { + code = 0; + } + + BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine + "\n"); + } + in.close(); + + return new ResponseJre(code, c.getResponseMessage(), response.toString(), c.getHeaderFields()); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java b/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java new file mode 100644 index 00000000..d234d854 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java @@ -0,0 +1,299 @@ +package com.google.gwt.query.vm; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Proxy; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import com.google.gwt.query.client.Binder; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQ; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.JsonFactory; +import com.google.gwt.query.client.builders.Name; +import com.google.gwt.query.rebind.JsonBuilderGenerator; + +public class JsonFactoryJre implements JsonFactory { + + static JsonFactoryJre jsonFactory = new JsonFactoryJre(); + + public static class JsonBuilderHandler implements InvocationHandler { + private JSONObject jsonObject; + + public JsonBuilderHandler() { + jsonObject = new JSONObject(); + } + + public JsonBuilderHandler(JSONObject j) { + jsonObject = j; + } + + public JsonBuilderHandler(String payload) throws Throwable { + jsonObject = new JSONObject(payload); + } + + @SuppressWarnings("unchecked") + private <T> Object jsonArrayToList(JSONArray j, Class<T> ctype, boolean isArray) { + List<T> l = new ArrayList<T>(); + for (int i = 0; j != null && i < j.length() ; i++) { + l.add((T)getValue(j, i, null, null, ctype, null)); + } + return l.isEmpty() ? null : isArray ? l.toArray((T[])Array.newInstance(ctype, l.size())) : l; + } + + private Object getValue(JSONArray arr, int idx, JSONObject obj, String attr, Class<?> clz, Method method) { + Object ret = null; + try { + if (clz.isArray() || clz.equals(List.class)) { + Class<?> ctype = Object.class; + if (clz.isArray()) { + ctype = clz.getComponentType(); + } else { + Type returnType = method.getGenericReturnType(); + if (returnType instanceof ParameterizedType) { + ctype = (Class<?>)((ParameterizedType) returnType).getActualTypeArguments()[0]; + } + } + ret = jsonArrayToList(obj.getJSONArray(attr), ctype, clz.isArray()); + } else if (clz.equals(Date.class)) { + ret = new Date(obj != null ? obj.getLong(attr): arr.getLong(idx)); + } else if (clz.equals(String.class)) { + ret = obj != null ? obj.getString(attr) : arr.getString(idx); + } else if (clz.equals(Boolean.class) || clz.isPrimitive() && clz == Boolean.TYPE) { + try { + ret = obj != null ? obj.getBoolean(attr): arr.getBoolean(idx); + } catch (Exception e) { + return Boolean.FALSE; + } + } else if (clz.equals(Byte.class) || clz.equals(Short.class) || clz.equals(Integer.class) + || clz.isPrimitive() && (clz == Byte.TYPE || clz == Short.TYPE || clz == Integer.TYPE)) { + try { + ret = obj != null ? obj.getInt(attr): arr.getInt(idx); + } catch (Exception e) { + return 0; + } + } else if (clz.equals(Double.class) || clz.equals(Float.class) + || clz.isPrimitive() && (clz == Double.TYPE || clz == Float.TYPE)) { + try { + ret = obj != null ? obj.getDouble(attr): arr.getDouble(idx); + } catch (Exception e) { + return .0; + } + } else if (clz.equals(Long.class) + || clz.isPrimitive() && clz == Long.TYPE) { + try { + ret = obj != null ? obj.getLong(attr): arr.getLong(idx); + } catch (Exception e) { + return 0l; + } + } else { + ret = obj != null ? obj.get(attr): arr.get(idx); + if (ret instanceof JSONObject) { + if (clz == Object.class) { + ret = jsonFactory.createBinder((JSONObject)ret); + } else if (Binder.class.isAssignableFrom(clz) && !clz.isAssignableFrom(ret.getClass())) { + ret = jsonFactory.create(clz, (JSONObject)ret); + } + } + } + } catch (JSONException e) { + } + return ret; + } + + private <T> JSONArray listToJsonArray(Object...l) throws Throwable { + JSONArray ret = new JSONArray(); + for (Object o: l) { + setValue(ret, null, null, o, null); + } + return ret; + } + + private Object setValue(JSONArray arr, JSONObject obj, String attr, Object o, Method method) { + try { + if (o == null) { + return o; + } + if (o instanceof String) { + return obj != null ? obj.put(attr, o) : arr.put(o); + } else if (o instanceof Boolean) { + return obj != null ? obj.put(attr, o) : arr.put(o); + } else if (o instanceof Number) { + return obj != null ? obj.put(attr, o) : arr.put(o); + } else if (o instanceof Date) { + return obj != null ? obj.put(attr, ((Date) o).getTime()) : arr.put(((Date) o).getTime()); + } else if (o instanceof Binder) { + return obj != null ? obj.put(attr, ((Binder) o).getBound()) : arr.put(((Binder) o).getBound()); + } else if (o.getClass().isArray() || o instanceof List) { + Object[] arg; + if (o.getClass().isArray()) { + arg = (Object[])o; + } else { + arg = ((List<?>)o).toArray(); + } + JSONArray a = listToJsonArray(arg); + return obj != null ? obj.put(attr, a) : arr.put(a); + } else { + if (!(o instanceof Function)) { + System.out.println("Unkown setter object " + attr + " " + o.getClass().getName() + " " + o); + } + return obj != null ? obj.put(attr, o) : arr.put(o); + } + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String mname = method.getName(); + Class<?>[] classes = method.getParameterTypes(); + int largs = classes.length; + + Name name = method.getAnnotation(Name.class); + String attr = name != null ? name.value() : deCapitalize(mname.replaceFirst("^[gs]et", "")); + + if ("getFieldNames".equals(mname)) { + return JSONObject.getNames(jsonObject); + } else if ("as".equals(mname)) { + Class<? extends JsonBuilder> clz = (Class<? extends JsonBuilder>)args[0]; + return jsonFactory.create(clz, jsonObject); + } else if ("getJsonName".equals(mname)) { + return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); + } else if (mname.matches("getProperties|getBound")) { + return jsonObject; + } else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) { + jsonObject = new JSONObject(String.valueOf(args[0])); + } else if (mname.matches("toString")) { + return jsonObject.toString(); + } else if (mname.matches("toJsonWithName")) { + String jsonName = JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); + return "{\"" + jsonName + "\":"+ jsonObject.toString() + "}"; + } else if (mname.matches("toJson")) { + return jsonObject.toString() ; + } else if ("toQueryString".equals(mname)) { + return param(jsonObject); + } else if (largs == 1 && mname.equals("get")) { + Class<?> ret = method.getReturnType(); + attr = String.valueOf(args[0]); + return getValue(null, 0, jsonObject, attr, ret, method); + } else if (largs == 0 || mname.startsWith("get")) { + Class<?> ret = method.getReturnType(); + return getValue(null, 0, jsonObject, attr, ret, method); + } else if (largs == 1 || mname.startsWith("set")) { + setValue(null, jsonObject, attr, args[0], method); + return proxy; + } + return null; + } + + private String deCapitalize(String s) { + return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s; + } + + private String getDataBindingClassName(Class<?> type) { + for (Class<?> c : type.getInterfaces()) { + if (c.equals(JsonBuilder.class)) { + return type.getName(); + } else { + return getDataBindingClassName(c); + } + } + return null; + } + + private String param(JSONObject o) { + String ret = ""; + for (String k : JSONObject.getNames(o)) { + ret += ret.isEmpty() ? "" : "&"; + JSONObject p = null; + JSONArray a = null; + String s = null; + try { + a = o.getJSONArray(k); + } catch (Exception e) { + } + if (a != null) { + for (int i = 0, l = a.length(); i < l ; i++) { + ret += i > 0 ? "&" : ""; + try { + p = a.getJSONObject(i); + } catch (Exception e) { + try { + s = String.valueOf(a.get(i)); + } catch (Exception d) { + } + } + if (p != null) { + ret += k + "[]=" + p.toString(); + } else if (s != null){ + ret += k + "[]=" + s; + } + } + } else { + try { + p = o.getJSONObject(k); + } catch (Exception e) { + try { + s = String.valueOf(o.get(k)); + } catch (Exception d) { + } + } + if (p != null) { + ret += k + "=" + p.toString(); + } else if (s != null) { + if (!s.isEmpty() && !"null".equalsIgnoreCase(s)) { + ret += k + "=" + s; + } + } + } + } + return ret; + } + } + + @SuppressWarnings("unchecked") + public <T> T create(Class<T> clz, JSONObject jso) { + InvocationHandler handler = new JsonBuilderHandler(jso); + return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] {clz}, handler); + } + + @SuppressWarnings("unchecked") + public <T extends JsonBuilder> T create(Class<T> clz) { + InvocationHandler handler = new JsonBuilderHandler(); + return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] {clz}, handler); + } + + public Binder createBinder() { + InvocationHandler handler = new JsonBuilderHandler(); + return (Binder)Proxy.newProxyInstance(Binder.class.getClassLoader(), new Class[] {Binder.class}, handler); + } + + public Binder createBinder(JSONObject jso) { + InvocationHandler handler = new JsonBuilderHandler(jso); + return (Binder)Proxy.newProxyInstance(Binder.class.getClassLoader(), new Class[] {Binder.class}, handler); + } + + @Override + public Binder create(String s) { + Binder ret = createBinder(); + ret.parse(Properties.wrapPropertiesString(s)); + return ret; + } + + @Override + public Binder create() { + return createBinder(); + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/vm/ResponseJre.java b/gwtquery-core/src/main/java/com/google/gwt/query/vm/ResponseJre.java new file mode 100644 index 00000000..36aafd37 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/ResponseJre.java @@ -0,0 +1,66 @@ +package com.google.gwt.query.vm; + +import java.util.List; +import java.util.Map; + +import com.google.gwt.http.client.Header; +import com.google.gwt.http.client.Response; + +/** + * Implementation of `Response` in the JVM + */ +public class ResponseJre extends Response { + private int status; + private Map<String,List<String>> headers; + private String responseText; + private String statusText; + + public ResponseJre(int status, String statusText, String text, Map<String,List<String>> headers) { + this.status = status; + this.headers = headers; + this.responseText = text; + this.statusText = statusText; + } + + public String getHeader(String header) { + List<String> l = headers.get(header); + if (l != null && !l.isEmpty()) { + String ret = ""; + for (String s : l) { + ret += ret.isEmpty() ? s : (", " + s); + } + return ret; + } + return null; + } + + public Header[] getHeaders() { + Header[] ret = new Header[headers.size()]; + int i = 0; + for (final String s : headers.keySet()) { + final String v = getHeader(s); + ret[i] = new Header() { + public String getValue() { + return v; + } + public String getName() { + return s; + } + }; + i++; + } + return ret; + } + public String getHeadersAsString() { + return null; + } + public int getStatusCode() { + return status; + } + public String getStatusText() { + return statusText; + } + public String getText() { + return responseText; + } +}
\ No newline at end of file diff --git a/gwtquery-core/src/main/super/com/google/gwt/query/super/com/google/gwt/query/client/GQ.java b/gwtquery-core/src/main/super/com/google/gwt/query/super/com/google/gwt/query/client/GQ.java new file mode 100644 index 00000000..732d2902 --- /dev/null +++ b/gwtquery-core/src/main/super/com/google/gwt/query/super/com/google/gwt/query/client/GQ.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.query.client.Binder; +import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.JsonFactory; +import com.google.gwt.query.client.plugins.ajax.AjaxTransportJs; +import com.google.gwt.query.client.plugins.ajax.Ajax.AjaxTransport; +import com.google.gwt.query.vm.AjaxTransportJre; +import com.google.gwt.query.vm.JsonFactoryJre; +import com.google.gwt.user.client.Window; + +public class GQ { + + private static JsonFactory jsonFactory; + private static AjaxTransport ajaxTransport; + + public static <T extends JsonBuilder> T create(Class<T> clz) { + return getFactory().create(clz); + } + + public static <T extends JsonBuilder> T create(Class<T> clz, String payload) { + T ret = create(clz); + ret.load(payload); + return ret; + } + + public static Binder create(String s) { + return getFactory().create(s); + } + + public static Binder create() { + return getFactory().create(); + } + + public static AjaxTransport getAjaxTransport() { + if (ajaxTransport == null) { + ajaxTransport = new AjaxTransportJs(); + } + return ajaxTransport; + } + + private static JsonFactory getFactory() { + if (jsonFactory == null) { + jsonFactory = GWT.<JsonFactory>create(JsonFactory.class); + } + return jsonFactory; + } +} diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/QueryTest.gwt.xml b/gwtquery-core/src/test/java/com/google/gwt/query/QueryTest.gwt.xml new file mode 100644 index 00000000..5b2b1d35 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/QueryTest.gwt.xml @@ -0,0 +1,21 @@ +<!-- + Copyright 2013, The gwtquery team. + + 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. +--> + +<module> + <inherits name='com.google.gwt.query.Query'/> + <servlet class='com.google.gwt.query.servlet.GQAjaxTestServlet' path="/test.json"/> + <servlet class='com.google.gwt.query.servlet.GQAjaxTestServlet' path="/test.upld"/> +</module> diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java index 65bd8c56..ee35efa2 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java @@ -1,5 +1,5 @@ /* - * Copyright 2011, The gwtquery team. + * Copyright 2013, The gwtquery team. * * 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 @@ -16,25 +16,19 @@ package com.google.gwt.query.client; +import static com.google.gwt.query.client.GQuery.$; + import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; -import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.builders.Name; import com.google.gwt.query.client.builders.XmlBuilder; import com.google.gwt.query.client.plugins.ajax.Ajax; -import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static com.google.gwt.query.client.GQuery.$; - /** * Test class for testing ajax stuff. */ @@ -45,7 +39,7 @@ public class GQueryAjaxTestGwt extends GWTTestCase { static HTML testPanel = null; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { @@ -64,78 +58,6 @@ public class GQueryAjaxTestGwt extends GWTTestCase { } } - interface Item extends JsonBuilder { - Date getDate(); - void setDate(Date d); - } - - interface JsonExample extends JsonBuilder { - int getA(); - JsonExample getB(); - @Name("M") - int getM(); - @Name("u") - String getUrl(); - long getD(); - Boolean getZ(); - String[] getT(); - JsonExample setT(String[] strings); - JsonExample setZ(Boolean b); - JsonExample setD(long l); - List<Item> getItems(); - void setItems(List<Item> a); - String y(); - void y(String s); - Function getF(); - void setF(Function f); - } - - boolean functionRun = false; - public void testJsonBuilder() { - String json = "{M:0, a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true}"; - JsonExample c = GWT.create(JsonExample.class); - assertEquals(0, c.getA()); - c.parse(json, true); - assertEquals(0, c.getM()); - assertEquals(1, c.getA()); - assertNotNull(c.getB()); - assertEquals(2, c.getB().getA()); - assertEquals(3, c.getB().getB().getA()); - assertTrue(c.getZ()); - assertEquals("hola", c.getT()[0]); - assertEquals("adios", c.getT()[1]); - assertEquals("url", c.getUrl()); - c.setT(new String[]{"foo", "bar"}) - .setZ(false).setD(1234); - assertFalse(c.getZ()); - assertEquals("foo", c.getT()[0]); - assertEquals("bar", c.getT()[1]); - assertEquals(1234l, c.getD()); - c.y("y"); - assertEquals("y", c.y()); - - c.setF(new Function() { - public void f() { - functionRun = true; - } - }); - assertFalse(functionRun); - c.getF().f(); - assertTrue(functionRun); - - Item i1 = GWT.create(Item.class); - Item i2 = GWT.create(Item.class); - i1.setDate(new Date(2000)); - i2.setDate(new Date(3000)); - Item[] items = new Item[]{i1, i2}; - c.setItems(Arrays.asList(items)); - assertEquals(2000l, c.getItems().get(0).getDate().getTime()); - assertEquals(3000l, c.getItems().get(1).getDate().getTime()); - String s = "{'M':0,'a':1,'b':{'a':2,'b':{'a':3}},'u':'url','d':1234,'t':['foo','bar']," + - "'z':false,'y':'y','items':[{'date':2000},{'date':3000}]}"; - assertEquals(s, c.toString().replaceAll("\"", "'")); - } - interface XmlExample extends XmlBuilder { interface T extends XmlBuilder { } @@ -244,100 +166,16 @@ public class GQueryAjaxTestGwt extends GWTTestCase { assertEquals("AName", f.getEntry()[0].getAuthor().getName().getText()); } - public void testJsonValidService() { - delayTestFinish(5000); - // Use a public json service - String testJsonpUrl = "https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?callback=?&key=NO-KEY"; - Ajax.getJSONP(testJsonpUrl, new Function(){ - public void f() { - Properties p = getDataProperties(); - // It should return error since we do not use a valid key - // {"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}} - assertEquals(400, p.getJavaScriptObject("error").<Properties>cast().getInt("code")); - finishTest(); - } - }, null, 0); - } - @DoNotRunWith({Platform.HtmlUnitLayout}) public void testJsonNonCallbackResponse() { delayTestFinish(5000); String testJsonpUrl = "http://www.google.com"; Ajax.getJSONP(testJsonpUrl, null, new Function(){ public void f() { - Properties p = getDataProperties(); + Properties p = arguments(0); assertNull(p); finishTest(); } }, 500); } - - public void testJsonpTimeout() { - delayTestFinish(5000); - String nonJsonpUrl = "http://127.0.0.1/nopage"; - - Settings s = Ajax.createSettings(); - s.setTimeout(1000); - s.setSuccess(new Function(){ - public void f() { - fail(); - } - }); - s.setError(new Function(){ - public void f() { - finishTest(); - } - }); - s.setDataType("jsonp"); - s.setUrl(nonJsonpUrl); - - Ajax.ajax(s); - } - - public void testAjaxError() { - delayTestFinish(5000); - String url = "http://127.0.0.1/nopage"; - - Ajax.ajax(Ajax.createSettings().setTimeout(1000).setUrl(url)) - .done(new Function(){ - public void f() { - fail(); - } - }).fail(new Function(){ - public void f() { - finishTest(); - } - }); - } - - public void testGetScript() { - delayTestFinish(5000); - String url = "http://code.jquery.com/jquery-2.0.3.min.js"; - Ajax.loadScript(url) - .done(new Function(){ - public void f() { - finishTest(); - } - }).fail(new Function(){ - public void f() { - fail(); - } - }); - } - - public void testGetScriptFail() { - delayTestFinish(5000); - String url = "http://127.0.0.1/nopage"; - Ajax.getScript(url) - .done(new Function(){ - public void f() { - fail(); - } - }).fail(new Function(){ - public void f() { - finishTest(); - } - }); - } - } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java index 50f99d6f..f5a5d157 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java @@ -82,7 +82,7 @@ public class GQueryCoreTestGwt extends GWTTestCase { int done = 0; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java index ea9b91dd..90654507 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCssTestGwt.java @@ -68,7 +68,7 @@ public class GQueryCssTestGwt extends GWTTestCase { static HTML testPanel = null; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java index 1ad4e907..2e0c6821 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryDeferredTestGwt.java @@ -39,7 +39,7 @@ public class GQueryDeferredTestGwt extends GWTTestCase { static HTML testPanel = null; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java index 8cf497db..ac79febe 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java @@ -41,7 +41,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { static HTML testPanel = null; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java index b781d1d9..681faa78 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEventsTestGwt.java @@ -14,6 +14,7 @@ package com.google.gwt.query.client; import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NodeList; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.junit.DoNotRunWith; @@ -68,7 +69,7 @@ public class GQueryEventsTestGwt extends GWTTestCase { int testSubmitEventCont = 0; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtSetUp() { @@ -996,17 +997,13 @@ public class GQueryEventsTestGwt extends GWTTestCase { public void testRebind() { final GQuery b = $("<p>content</p>"); assertEquals(1, b.size()); - assertEquals(1, b.get().getLength()); b.click(new Function() { public void f(Element e) { b.css(CSS.COLOR.with(RGBColor.RED)); } }); $(e).append(b); - // TODO: dom manipulations some times modifies gquery nodelist, - // we could remove the nodelist since we maintain a list of elements. assertEquals(1, b.size()); - assertEquals(1, b.get().getLength()); b.click(); assertEquals("red", b.css("color", false)); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryGwtSuiteTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryGwtSuiteTest.java index eeecd7a1..0bda7e76 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryGwtSuiteTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryGwtSuiteTest.java @@ -3,6 +3,10 @@ package com.google.gwt.query.client; import junit.framework.Test; import com.google.gwt.junit.tools.GWTTestSuite; +import com.google.gwt.query.client.ajax.AjaxTestJre; +import com.google.gwt.query.client.ajax.AjaxTestGwt; +import com.google.gwt.query.client.dbinding.DataBindingTestJre; +import com.google.gwt.query.client.dbinding.DataBindingTestGwt; import com.google.gwt.query.client.deferred.DeferredTestGwt; import com.google.gwt.query.client.impl.SelectorEnginesTestGwt; @@ -10,12 +14,14 @@ import com.google.gwt.query.client.impl.SelectorEnginesTestGwt; * Class to run all Gwt test in a jvm instance. * It speeds up maven testing phase. */ -public class GQueryGwtSuiteTest extends GWTTestSuite -{ - public static Test suite() - { +public class GQueryGwtSuiteTest extends GWTTestSuite { + public static Test suite() { GWTTestSuite suite = new GWTTestSuite( "GQuery Suite" ); + suite.addTestSuite(AjaxTestJre.class); + suite.addTestSuite(DataBindingTestJre.class); + suite.addTestSuite(DataBindingTestGwt.class); suite.addTestSuite(GQueryAjaxTestGwt.class); + suite.addTestSuite(AjaxTestGwt.class); suite.addTestSuite(GQueryDeferredTestGwt.class); suite.addTestSuite(DeferredTestGwt.class); suite.addTestSuite(GQuerySelectorsTestGwt.class); diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java index 74f91d12..a15af268 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryJsTestGwt.java @@ -34,7 +34,7 @@ public class GQueryJsTestGwt extends GWTTestCase { static HTML testPanel = null; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtSetUp() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java index 36083eee..d60eb9a0 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTestGwt.java @@ -175,7 +175,7 @@ public class GQuerySelectorsTestGwt extends GWTTestCase { }-*/; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void gwtTearDown() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java index c5399e83..b509fa00 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryWidgetsTestGwt.java @@ -44,7 +44,7 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { int testSubmitEventCont = 0; public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } public void testGWTQueryCoreWidgets() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestGwt.java new file mode 100644 index 00000000..69b0021a --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestGwt.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client.ajax; + +import com.google.gwt.core.client.GWT; + + +/** + * Test for data binding and Ajax which is run in gwt + */ +public class AjaxTestGwt extends AjaxTests { + + @Override + public String getModuleName() { + return "com.google.gwt.query.QueryTest"; + } + + protected void gwtSetUp() throws Exception { + echoUrl = GWT.getHostPageBaseURL() + servletPath; + echoUrlCORS = echoUrl.replaceFirst("http://[\\d\\.]+:", "http://localhost:") + "?cors=true"; + } +} diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java new file mode 100644 index 00000000..abe00e30 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java @@ -0,0 +1,103 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client.ajax; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.servlet.Servlet; + +import org.mortbay.jetty.Server; +import org.mortbay.jetty.handler.HandlerWrapper; +import org.mortbay.jetty.servlet.DefaultServlet; +import org.mortbay.jetty.webapp.WebAppClassLoader; +import org.mortbay.jetty.webapp.WebAppContext; + +import com.google.gwt.query.servlet.GQAjaxTestServlet; +import com.google.gwt.query.vm.AjaxTransportJre; + +/** + * Tests for Data Binders and Ajax run in the JVM + */ +public class AjaxTestJre extends AjaxTests { + + static Server server; + static int port = new Random().nextInt(1000) + 2000; + + public String getModuleName() { + return null; + } + + public AjaxTestJre() throws Exception { + String localDomain = "http://127.0.0.1:" + port; + AjaxTransportJre.enableCORS(localDomain); + String corsDomain = "http://localhost:" + port; + + echoUrl = localDomain + "/" + servletPath; + echoUrlCORS = corsDomain + "/" + servletPath + "?cors=true"; + startWebServer(port); + } + + protected void startWebServer(int port) throws Exception { + if (server == null) { + final Map<String, Class<? extends Servlet>> servlets = new HashMap<String, Class<? extends Servlet>>(); + servlets.put("/" + servletPath, GQAjaxTestServlet.class); + server = createWebServer(port, ".", null, servlets, null); + } + } + + public static Server createWebServer(final int port, final String resourceBase, final String[] classpath, + final Map<String, Class<? extends Servlet>> servlets, final HandlerWrapper handler) throws Exception { + + final Server server = new Server(port); + + final WebAppContext context = new WebAppContext(); + context.setContextPath("/"); + context.setResourceBase(resourceBase); + + if (servlets != null) { + for (final Map.Entry<String, Class<? extends Servlet>> entry : servlets.entrySet()) { + final String pathSpec = entry.getKey(); + final Class<? extends Servlet> servlet = entry.getValue(); + context.addServlet(servlet, pathSpec); + + // disable defaults if someone likes to register his own root servlet + if ("/".equals(pathSpec)) { + context.setDefaultsDescriptor(null); + context.addServlet(DefaultServlet.class, "/favicon.ico"); + } + } + } + + final WebAppClassLoader loader = new WebAppClassLoader(context); + if (classpath != null) { + for (final String path : classpath) { + loader.addClassPath(path); + } + } + context.setClassLoader(loader); + if (handler != null) { + handler.setHandler(context); + server.setHandler(handler); + } else { + server.setHandler(context); + } + server.start(); + return server; + } + +}
\ No newline at end of file diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java new file mode 100644 index 00000000..f6a064c5 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java @@ -0,0 +1,252 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client.ajax; + +import com.google.gwt.http.client.Response; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.Platform; +import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.query.client.Binder; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQ; +import com.google.gwt.query.client.Promise; +import com.google.gwt.query.client.plugins.ajax.Ajax; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; + +/** + * Common Tests for Data Binding and Ajax which can run either in JVM and GWT + */ +public abstract class AjaxTests extends GWTTestCase { + + protected String echoUrl, echoUrlCORS; + protected Binder json, jsonGET; + protected String servletPath = "test.json"; + + private Function failFunction = new Function() { + public void f() { + fail(); + } + }; + + private Function finishFunction = new Function() { + public void f() { + finishTest(); + } + }; + + public AjaxTests() { + jsonGET = GQ.create("data: {a: abc, d: def}"); + json = GQ.create("a: abc, d: def"); + } + + private Promise performAjaxJsonTest(Settings s) { + delayTestFinish(5000); + return Ajax.ajax(s) + .done(new Function(){public void f() { + Binder p = arguments(0); + assertEquals("abc", p.get("a")); + finishTest(); + }}) + .fail(failFunction); + } + + private Promise performAjaxJsonTest_CORS(Settings s) { + return performAjaxJsonTest(s) + .done(new Function() {public void f() { + Response r = arguments(3); + assertNotNull(r.getHeader("Access-Control-Allow-Origin")); + }}); + } + + public void testAjaxJsonPost() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + .setUrl(echoUrl) + .setData(json) + .setDataType("json") + .setUsername("testuser") + .setPassword("testpassword"); + + performAjaxJsonTest(s); + } + + // This test needs htmlunit at least 2.11 + // https://groups.google.com/forum/#!msg/google-web-toolkit/dmyTt1Bh0pM/lBTIFiTyrpkJ + // + // It is necessary to patch RunStyleHtmlUnit because GWT default browser is FF3 since + // minimun version in htmlunit-2.1x is FF3.6 + // It is necessary to patch BrowserChannel as well because convertFromJavaValue receives + // non string objects under certain circumstances. + @DoNotRunWith(Platform.HtmlUnitBug) + public void testAjaxJsonPost_CORS() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + .setUrl(echoUrlCORS) + .setData(json) + .setDataType("json"); + + performAjaxJsonTest_CORS(s); + } + + public void testAjaxJsonGet() { + Settings s = Ajax.createSettings() + .setType("get") + .setUrl(echoUrl) + .setData(jsonGET) + .setDataType("json"); + + performAjaxJsonTest(s); + } + + @DoNotRunWith(Platform.HtmlUnitBug) + public void testAjaxJsonGet_CORS() { + Settings s = Ajax.createSettings() + .setType("get") + .setUrl(echoUrlCORS) + .setData(jsonGET) + .setDataType("json"); + + performAjaxJsonTest_CORS(s); + } + + public void testAjaxGetJsonP() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + .setType("post") + .setUrl(echoUrlCORS) + .setData(jsonGET) + .setDataType("jsonp"); + + performAjaxJsonTest(s); + } + + public void testJsonValidService() { + delayTestFinish(5000); + // Use a public json service supporting callback parameter + Ajax.getJSONP("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?callback=?&key=NO-KEY") + .done(new Function(){ + public void f() { + Binder p = arguments(0); + // It should return error since we do not use a valid key + // {"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}} + assertEquals(400, p.<Binder>get("error").<Number>get("code").intValue()); + finishTest(); + } + }) + .fail(failFunction); + } + + public void testInvalidOrigin() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + // Use a public json service non CORS enabled + .setUrl("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?key=NO-KEY") + .setDataType("json") + .setTimeout(1000); + + Ajax.ajax(s) + .done(failFunction) + .fail(finishFunction); + } + + public void testJsonInvalidService() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + // Use a valid javascript which does not wrap content in a callback + .setUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js") + .setDataType("jsonp") + .setTimeout(1000); + + Ajax.ajax(s) + .done(failFunction) + .fail(finishFunction); + } + + // For some reason htmlunit 2.16 does not raises a timeout, 2.9 does though, + // when server sleeps or connection lasts a while. Tested with htmlunit 2.16 + // @DoNotRunWith(Platform.HtmlUnitBug) + public void testAjaxTimeout() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + .setTimeout(100) + .setType("get") + // Connecting to private networks out of our LAN raises a timeout because + // there is no route for them in public networks. + .setUrl("http://10.32.45.67:7654"); + + Ajax.ajax(s) + .done(failFunction) + .fail(finishFunction); + } + + public void testJsonpTimeout() { + delayTestFinish(5000); + Settings s = Ajax.createSettings() + .setTimeout(1000) + .setDataType("jsonp") + .setUrl(echoUrl + "?timeout=2000"); + + Ajax.ajax(s) + .done(failFunction) + .fail(finishFunction); + } + + public void testAjaxError() { + delayTestFinish(5000); + String url = "http://127.0.0.1/nopage"; + + Ajax.ajax(Ajax.createSettings().setTimeout(1000).setUrl(url)) + .done(new Function(){ + public void f() { + fail(); + } + }).fail(new Function(){ + public void f() { + finishTest(); + } + }); + } + + public void testLoadScript() { + delayTestFinish(5000); + String url = "http://code.jquery.com/jquery-2.0.3.min.js"; + Ajax.loadScript(url) + .done(new Function(){ + public void f() { + finishTest(); + } + }).fail(new Function(){ + public void f() { + fail(); + } + }); + } + + public void testGetScriptFail() { + delayTestFinish(5000); + String url = "http://127.0.0.1/nopage"; + Ajax.getScript(url) + .done(new Function(){ + public void f() { + fail(); + } + }).fail(new Function(){ + public void f() { + finishTest(); + } + }); + } +}
\ No newline at end of file diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestGwt.java new file mode 100644 index 00000000..3cd087ce --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestGwt.java @@ -0,0 +1,29 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client.dbinding; + + +/** + * Test for data binding shared code run in gwt + */ +public class DataBindingTestGwt extends DataBindingTestJre { + + @Override + public String getModuleName() { + return "com.google.gwt.query.QueryTest"; + } + +} diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java new file mode 100644 index 00000000..9fa9a555 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java @@ -0,0 +1,117 @@ +/* + * Copyright 2013, The gwtquery team. + * + * 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 com.google.gwt.query.client.dbinding; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.GQ; +import com.google.gwt.query.client.builders.JsonBuilder; +import com.google.gwt.query.client.builders.Name; + +/** + * Tests for Deferred which can run either in JVM and GWT + */ +public class DataBindingTestJre extends GWTTestCase { + + public String getModuleName() { + return null; + } + + public interface Item extends JsonBuilder { + Date getDate(); + void setDate(Date d); + } + + public interface JsonExample extends JsonBuilder { + int getA(); + JsonExample getB(); + @Name("M") + int getM(); + @Name("u") + String getUrl(); + long getD(); + Boolean getZ(); + String[] getT(); + JsonExample setT(String[] strings); + JsonExample setZ(Boolean b); + JsonExample setD(long l); + List<Item> getItems(); + void setItems(List<Item> a); + String y(); + void y(String s); + Function getF(); + void setF(Function f); + } + + boolean functionRun = false; + public void testJsonBuilder() { + String json = "{M:0, a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true, 'items':[{'date':100}]}"; + + JsonExample c = GQ.create(JsonExample.class); + assertEquals(0, c.getA()); + c.parse(json, true); + + assertEquals(0, c.getM()); + assertEquals(1, c.getA()); + assertNotNull(c.getB()); + assertEquals(2, c.getB().getA()); + assertEquals(3, c.getB().getB().getA()); + assertTrue(c.getZ()); + assertEquals("hola", c.getT()[0]); + assertEquals("adios", c.getT()[1]); + assertEquals("url", c.getUrl()); + c.setT(new String[]{"foo", "bar"}) + .setZ(false).setD(1234); + assertFalse(c.getZ()); + assertEquals("foo", c.getT()[0]); + assertEquals("bar", c.getT()[1]); + assertEquals(1234l, c.getD()); + c.y("y"); + assertEquals("y", c.y()); + assertEquals(1, c.getItems().size()); + + c.setF(new Function() { + public void f() { + functionRun = true; + } + }); + assertFalse(functionRun); + c.getF().f(); + assertTrue(functionRun); + + Item i1 = GQ.create(Item.class); + Item i2 = GQ.create(Item.class); + i1.setDate(new Date(2000)); + i2.setDate(new Date(3000)); + Item[] items = new Item[]{i1, i2}; + c.setItems(Arrays.asList(items)); + assertEquals(2000l, c.getItems().get(0).getDate().getTime()); + assertEquals(3000l, c.getItems().get(1).getDate().getTime()); + + assertFalse(c.toJson().startsWith("{\"jsonExample\":")); + assertTrue(c.toJsonWithName().startsWith("{\"jsonExample\":")); + assertTrue(c.toJson().contains("\"items\":[{\"date\":")); + assertTrue(c.toQueryString().contains("t[]=bar")); + assertTrue(c.toQueryString().contains("a=1")); + assertTrue(c.toQueryString().contains("\"a\":2")); + + assertEquals(1, c.<Number>get("a").intValue()); + } +}
\ No newline at end of file diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/deferred/DeferredTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/deferred/DeferredTestGwt.java index de6375db..f972d3db 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/deferred/DeferredTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/deferred/DeferredTestGwt.java @@ -23,7 +23,7 @@ public class DeferredTestGwt extends DeferredTest { @Override public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java index 57c7749a..8dd79411 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTestGwt.java @@ -23,7 +23,7 @@ public class SelectorEnginesTestGwt extends SelectorEnginesTest { @Override public String getModuleName() { - return "com.google.gwt.query.Query"; + return "com.google.gwt.query.QueryTest"; } } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/servlet/GQAjaxTestServlet.java b/gwtquery-core/src/test/java/com/google/gwt/query/servlet/GQAjaxTestServlet.java new file mode 100644 index 00000000..a41dd1d7 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/servlet/GQAjaxTestServlet.java @@ -0,0 +1,81 @@ +package com.google.gwt.query.servlet; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class GQAjaxTestServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private String name = this.getClass().getSimpleName() + " "; + + @SuppressWarnings("unused") + private void dumpHeaders(HttpServletRequest req) { + System.out.println(name + req.getMethod() + " " + req.getContentType()); + + @SuppressWarnings("unchecked") + Enumeration<String> en = req.getHeaderNames(); + while (en.hasMoreElements()) { + String s = (String) en.nextElement(); + System.out.println(name + s + " " + req.getHeader(s)); + } + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + String t = req.getParameter("timeout"); + if (t != null && t.matches("\\d+")) { + try { + int ms = Integer.parseInt(t); + System.out.println(" Sleeping: " + ms); + Thread.sleep(ms); + } catch (Exception e) { + } + System.out.println(name + "timeout"); + return; + } + + String data = ""; + if (req.getMethod().equalsIgnoreCase("get")) { + data = req.getParameter("data") != null ? req.getParameter("data") : ""; + if (req.getParameter("callback") != null) { + data = req.getParameter("callback") + "(" + data + ");"; + } + } else if (req.getMethod().equalsIgnoreCase("post") + && req.getContentType().toLowerCase().startsWith("application/json")) { + BufferedReader reader = req.getReader(); + String line; + while ((line = reader.readLine()) != null) + data += line; + } + + String origin = req.getHeader("Origin"); + if ("true".equals(req.getParameter("cors")) && origin != null) { + resp.addHeader("Access-Control-Allow-Origin", origin); + resp.addHeader("Access-Control-Allow-Credentials", "true"); + String method = req.getHeader("Access-Control-Request-Method"); + if (method != null) { + resp.addHeader("Access-Control-Allow-Methods", method); + resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS"); + } + String headers = req.getHeader("Access-Control-Request-Headers"); + if (headers != null) { + resp.addHeader("Access-Control-Allow-Headers", headers); + } + } + + PrintWriter p = resp.getWriter(); + p.print(data); + p.flush(); + p.close(); + + System.out.println(name + "returns: " + data); + } +} |