diff options
author | Manuel Carrasco <manolo@apache.org> | 2014-02-03 06:53:27 -0800 |
---|---|---|
committer | Manuel Carrasco <manolo@apache.org> | 2014-02-03 06:53:27 -0800 |
commit | b415e6a811f3e29bc401f94de0dbaf4a53bc597c (patch) | |
tree | 4fefd94e203833913cf310b74c2d85d15fbc6283 | |
parent | b0bdc105cbb04164d5b82d7383af99f67882e539 (diff) | |
parent | 96705cf9e96e8e78771bfd4376cca90d00f4fbc8 (diff) | |
download | gwtquery-b415e6a811f3e29bc401f94de0dbaf4a53bc597c.tar.gz gwtquery-b415e6a811f3e29bc401f94de0dbaf4a53bc597c.zip |
Merge pull request #264 from gwtquery/mcm_jsonbuilder_jvm
JVM support for Json data binding and Ajax
47 files changed, 2309 insertions, 401 deletions
diff --git a/extractInterface.pl b/extractInterface.pl index c0510ee8..c1b1e6b5 100644 --- a/extractInterface.pl +++ b/extractInterface.pl @@ -76,6 +76,7 @@ close(F); my $class = "public interface $oclass"; if ($lazy) { $class .= "<T> extends LazyBase<T>" if ($lazy); + $head .= "import com.google.gwt.query.client.GQuery.*;\n"; $head .= "import com.google.gwt.query.client.LazyBase;\n\n"; } diff --git a/gwtquery-core/pom.xml b/gwtquery-core/pom.xml index a90c6a82..1514e2e5 100644 --- a/gwtquery-core/pom.xml +++ b/gwtquery-core/pom.xml @@ -16,7 +16,6 @@ <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> - <type>jar</type> <scope>test</scope> </dependency> <dependency> @@ -51,7 +50,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/GQ.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java new file mode 100644 index 00000000..292321b8 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java @@ -0,0 +1,104 @@ +/* + * 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; + +/** + * A set of useful methods for gQuery which can be run in browser or JVM. + */ +public abstract class GQ { + + private static AjaxTransport ajaxTransport; + + private static JsonFactory jsonFactory; + + public static IsProperties create() { + return getFactory().create(); + } + + /** + * Create an instance of a JsonBuilder object whose type is <T> + */ + public static <T extends JsonBuilder> T create(Class<T> clz) { + return getFactory().create(clz); + } + + /** + * Create an instance of a JsonBuilder object whose type is <T> + * and set the the underlying properties object. + */ + public static <T extends JsonBuilder> T create(Class<T> clz, IsProperties obj) { + T ret = create(clz); + ret.load(obj.getDataImpl()); + return ret; + } + + /** + * Create an instance of a JsonBuilder object whose type is <T> + * and load all its properties from a json string. + */ + public static <T extends JsonBuilder> T create(Class<T> clz, String payload) { + T ret = create(clz); + ret.load(payload); + return ret; + } + + /** + * Create an instance of IsProperties. Normally a Properties javascript + * object in client side, or a proxy object in the JVM + */ + public static IsProperties create(String s) { + return getFactory().create(s); + } + + /** + * Return the appropriate transport implementation depending on the runtime + * environment: browser or JVM + */ + 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; + } + + /** + * Change the default Ajax transport by a customized one, useful for + * testing purposes. + */ + public static void setAjaxTransport(AjaxTransport transport) { + ajaxTransport = transport; + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/IsProperties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/IsProperties.java new file mode 100644 index 00000000..bcd79cdb --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/IsProperties.java @@ -0,0 +1,86 @@ +/* + * 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 IsProperties { + /** + * load a properties object. + */ + <T extends IsProperties> T load(Object prp); + + /** + * parses a json string and loads the resulting properties object. + */ + <T extends IsProperties> T parse(String json); + + /** + * Returns the underlying object, normally a Properties jso in client + * and a Json implementation in the JVM. + */ + <T> T getDataImpl(); + + /** + * Return the Object with the given key. + */ + <T> T get(Object key); + + /** + * Set an Object with the given key. + */ + <T extends IsProperties> 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(); + + + /** + * converts a JsonBuilder instance into another JsonBuilder type but + * preserving the underlying data object. + */ + <T extends JsonBuilder> T as (Class<T> clz); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java index da25dba4..804e533b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/LazyGQuery.java @@ -12,23 +12,61 @@ * the License. */ package com.google.gwt.query.client; -import java.util.List; -import java.util.Map; - +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; +import com.google.gwt.core.client.JsArrayMixed; +import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.core.client.ScriptInjector; +import com.google.gwt.dom.client.BodyElement; +import com.google.gwt.dom.client.ButtonElement; +import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.InputElement; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; +import com.google.gwt.dom.client.OptionElement; +import com.google.gwt.dom.client.SelectElement; +import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.HasCssName; -import com.google.gwt.query.client.GQuery.Offset; +import com.google.gwt.dom.client.TextAreaElement; import com.google.gwt.query.client.css.CSS; import com.google.gwt.query.client.css.HasCssValue; import com.google.gwt.query.client.css.TakesCssValue; import com.google.gwt.query.client.css.TakesCssValue.CssSetter; +import com.google.gwt.query.client.impl.AttributeImpl; +import com.google.gwt.query.client.impl.DocumentStyleImpl; +import com.google.gwt.query.client.impl.SelectorEngine; +import com.google.gwt.query.client.js.JsCache; +import com.google.gwt.query.client.js.JsMap; import com.google.gwt.query.client.js.JsNamedArray; import com.google.gwt.query.client.js.JsNodeArray; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.js.JsUtils; import com.google.gwt.query.client.plugins.Effects; +import com.google.gwt.query.client.plugins.Events; +import com.google.gwt.query.client.plugins.Plugin; +import com.google.gwt.query.client.plugins.Widgets; +import com.google.gwt.query.client.plugins.ajax.Ajax; +import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; +import com.google.gwt.query.client.plugins.deferred.Deferred; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; +import com.google.gwt.query.client.plugins.events.EventsListener; +import com.google.gwt.query.client.plugins.widgets.WidgetsUtils; +import com.google.gwt.regexp.shared.RegExp; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Widget; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import static com.google.gwt.query.client.plugins.QueuePlugin.Queue; +import com.google.gwt.query.client.GQuery.*; +import com.google.gwt.query.client.LazyBase; public interface LazyGQuery<T> extends LazyBase<T>{ @@ -705,6 +743,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * <pre> * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); * </pre> + * @deprecated use {@link #on(String, String, Function...)} */ LazyGQuery<T> delegate(String selector, int eventbits, Function... handlers); @@ -743,6 +782,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * <pre> * $("div.main").delegate(".subMain", Event.ONCLICK | Event.ONDBLCLICK, new Function(){...}); * </pre> + * @deprecated use {@link #on(String, String, Object, Function...)} */ LazyGQuery<T> delegate(String selector, int eventbits, Object data, Function... handlers); @@ -783,6 +823,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * </pre> * * </pre> + * @deprecated use {@link #on(String, String, Function...)} */ LazyGQuery<T> delegate(String selector, String eventType, Function... handlers); @@ -821,6 +862,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * </pre> * * </pre> + * @deprecated use {@link #on(String, String, Object, Function...)} */ LazyGQuery<T> delegate(String selector, String eventType, Object data, Function... handlers); @@ -860,6 +902,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Remove all event handlers previously attached using {@link #live(String, Function)}. In order * for this method to function correctly, the selector used with it must match exactly the * selector initially used with {@link #live(String, Function)} + * @deprecated use {@link #off(String, String)} instead */ LazyGQuery<T> die(); @@ -867,6 +910,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * Remove an event handlers previously attached using {@link #live(int, Function)} In order for * this method to function correctly, the selector used with it must match exactly the selector * initially used with {@link #live(int, Function)} + * @deprecated use {@link #off(String)} */ LazyGQuery<T> die(int eventbits); @@ -1119,6 +1163,11 @@ public interface LazyGQuery<T> extends LazyBase<T>{ int index(Element element); /** + * Return the position of the first matched element in relation with its sibblings. + */ + int index(); + + /** * Returns the inner height of the first matched element, including padding but not the vertical * scrollbar height, border, or margin. */ @@ -1237,12 +1286,14 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Attach a handler for this event to all elements which match the current selector, now and in * the future. + * @deprecated use {@link #on(String, Function...)} */ LazyGQuery<T> live(int eventbits, Function... funcs); /** * Attach a handler for this event to all elements which match the current selector, now and in * the future. + * @deprecated use {@link #on(String, Object, Function...)} */ LazyGQuery<T> live(int eventbits, Object data, Function... funcs); @@ -1295,6 +1346,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * descendant of myElement.</li> * </ul> * </p> + * @deprecated use {@link #on(String, Function...)} */ LazyGQuery<T> live(String eventName, Function... funcs); @@ -1347,6 +1399,7 @@ public interface LazyGQuery<T> extends LazyBase<T>{ * descendant of myElement.</li> * </ul> * </p> + * @deprecated use {@link #on(String, Object, Function...)} */ LazyGQuery<T> live(String eventName, Object data, Function... funcs); @@ -1555,6 +1608,46 @@ public interface LazyGQuery<T> extends LazyBase<T>{ LazyGQuery<T> offsetParent(); /** + * Attach an event handler function for one or more events to the selected elements. + */ + LazyGQuery<T> on(String eventName, Function... funcs); + + /** + * Attach an event handler function for one or more events to the selected elements. + */ + LazyGQuery<T> on(String eventName, Object data, Function... funcs); + + /** + * Attach an event handler function for one or more events to the selected elements. + */ + LazyGQuery<T> on(String eventName, String selector, Function... funcs); + + /** + * Attach an event handler function for one or more events to the selected elements. + */ + LazyGQuery<T> on(String eventName, String selector, Object data, Function... funcs); + + /** + * Remove all event handlers. + */ + LazyGQuery<T> off(); + + /** + * Remove an event handler + */ + LazyGQuery<T> off(String eventName); + + /** + * Remove an event handler + */ + LazyGQuery<T> off(String eventName, Function f); + + /** + * Remove an event handler + */ + LazyGQuery<T> off(String eventName, String selector); + + /** * Binds a handler to a particular Event (like Event.ONCLICK) for each matched element. The * handler is executed only once for each element. * @@ -2232,24 +2325,28 @@ public interface LazyGQuery<T> extends LazyBase<T>{ /** * Remove all event delegation that have been bound using * {@link #delegate(String, int, Function...)} {@link #live(int, Function...)} methods + * @deprecated use {@link #off()} */ LazyGQuery<T> undelegate(); /** * Undelegate is a way of removing event handlers that have been bound using * {@link #delegate(String, int, Function...)} method + * @deprecated use {@link #off(String)} */ LazyGQuery<T> undelegate(String selector); /** * Undelegate is a way of removing event handlers that have been bound using * {@link #delegate(String, int, Function...)} method + * @deprecated use {@link #off(String)} */ LazyGQuery<T> undelegate(String selector, int eventBit); /** * Undelegate is a way of removing event handlers that have been bound using * {@link #delegate(String, int, Function...)} method + * @deprecated use {@link #off(String, String)} */ LazyGQuery<T> undelegate(String selector, String eventName); 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..ed39d4eb 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 IsProperties { 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,46 @@ public class Properties extends JavaScriptObject { return c().length() == 0; } + public final <J extends IsProperties> J load(Object prp) { + c().clear(); + if (prp instanceof JsCache) { + c().copy((JsCache)prp); + } + return getDataImpl(); + } + + public final <J extends IsProperties> 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 toJsonWithName(getJsonName()); + } + + public final String toJsonWithName(String name) { + return "{\"" + name + "\":{" + toJson() + "}"; + } + + @SuppressWarnings("unchecked") + public final <J> J getDataImpl() { + 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..b5f30451 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.IsProperties; + /** * 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 IsProperties { /** * 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..8ccc9e75 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.IsProperties; 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>getDataImpl()); } 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 getDataImpl() { + return p; + } + + public <T> T get(Object key) { + return p.get(key); + } + + @SuppressWarnings("unchecked") + public <T extends IsProperties> T set(Object key, Object val) { + if (val instanceof IsProperties) { + p.set(key, ((IsProperties)val).getDataImpl()); + } 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..847fcfbd --- /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.IsProperties; + +public interface JsonFactory { + <T extends JsonBuilder> T create(Class<T> clz); + IsProperties create(String s); + IsProperties create(); +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/ConsoleBrowser.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/ConsoleBrowser.java index 985e3a03..dd67bd1a 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/ConsoleBrowser.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/ConsoleBrowser.java @@ -43,13 +43,13 @@ public class ConsoleBrowser implements Console { * See: http://whattheheadsaid.com/2011/04/internet-explorer-9s-problematic-console-object */ private static class ConsoleIe9 extends ConsoleImpl { - + private boolean initialized = false; - + public ConsoleIe9(){ init(); } - + protected native void init()/*-{ try { [ "log", "info", "warn", "error", "dir", "clear", "profile", "profileEnd" ] @@ -60,7 +60,7 @@ public class ConsoleBrowser implements Console { } catch(e) { } }-*/; - + @Override public void clear() { if (initialized) super.clear(); @@ -102,7 +102,7 @@ public class ConsoleBrowser implements Console { @Override public void timeEnd(String title) {} } - + /** * Default implementation: webkit, opera, FF, ie10 */ @@ -163,9 +163,9 @@ public class ConsoleBrowser implements Console { $wnd.console.warn(arg); }-*/; } - + private ConsoleImpl impl; - + public ConsoleBrowser() { impl = GQuery.browser.ie8? new ConsoleIe8(): GQuery.browser.ie9? new ConsoleIe9(): new ConsoleImpl(); } @@ -239,7 +239,7 @@ public class ConsoleBrowser implements Console { public void warn(Object arg) { impl.warn(toJs(arg)); } - + /** * Don't pass GWT Objects to JS methods */ 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/LazyEffects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java index 2a921a4e..cf62be4f 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEffects.java @@ -25,6 +25,7 @@ import com.google.gwt.query.client.plugins.effects.Fx; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve; import com.google.gwt.query.client.plugins.effects.TransitionsAnimation.TransitionsClipAnimation; +import com.google.gwt.query.client.GQuery.*; import com.google.gwt.query.client.LazyBase; public interface LazyEffects<T> extends LazyBase<T>{ diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java index c0689af6..37244237 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java @@ -23,6 +23,7 @@ import com.google.gwt.query.client.plugins.events.EventsListener; import com.google.gwt.query.client.plugins.events.EventsListener.SpecialEvent; import com.google.gwt.query.client.plugins.events.GqEvent; import com.google.gwt.user.client.Event; +import com.google.gwt.query.client.GQuery.*; import com.google.gwt.query.client.LazyBase; public interface LazyEvents<T> extends LazyBase<T>{ @@ -153,6 +154,8 @@ public interface LazyEvents<T> extends LazyBase<T>{ */ LazyEvents<T> unbind(int eventbits); + LazyEvents<T> off(); + /** * Removes all handlers, that matches the events bits and the namespace passed, from each element. * diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java index 5fe7de8b..8c40c293 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyWidgets.java @@ -33,6 +33,7 @@ import com.google.gwt.user.client.ui.PasswordTextBox; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.query.client.GQuery.*; import com.google.gwt.query.client.LazyBase; public interface LazyWidgets<T> extends LazyBase<T>{ 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..7b472ba5 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.IsProperties; 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; +import com.google.gwt.user.client.ui.FormPanel; /** * Ajax class for GQuery. @@ -32,6 +31,20 @@ import com.google.gwt.query.client.plugins.deferred.PromiseReqBuilderJSONP; * */ public class Ajax extends GQuery { + + public static final String JSON_CONTENT_TYPE = "application/json"; + + public static final String JSON_CONTENT_TYPE_UTF8 = JSON_CONTENT_TYPE + "; charset=utf-8"; + + public static interface AjaxTransport { + Promise getJsonP(Settings settings); + + Promise getLoadScript(Settings settings); + + Promise getXhr(Settings settings); + } + + static AjaxTransport transport = GQ.getAjaxTransport(); /** * Ajax Settings object @@ -39,30 +52,32 @@ public class Ajax extends GQuery { public interface Settings extends JsonBuilder { String getContentType(); Element getContext(); - Properties getData(); + IsProperties getData(); String getDataString(); String getDataType(); Function getError(); - Properties getHeaders(); + IsProperties getHeaders(); String getPassword(); Function getSuccess(); int getTimeout(); String getType(); String getUrl(); String getUsername(); + boolean getWithCredentials(); 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(IsProperties p); Settings setPassword(String p); Settings setSuccess(Function f); Settings setTimeout(int t); Settings setType(String t); Settings setUrl(String u); Settings setUsername(String u); + Settings setWithCredentials(boolean b); } public static final Class<Ajax> Ajax = registerPlugin(Ajax.class, new Plugin<Ajax>() { @@ -71,7 +86,7 @@ public class Ajax extends GQuery { } }); - public static Promise ajax(Properties p) { + public static Promise ajax(IsProperties p) { Settings s = createSettings(); s.load(p); return ajax(s); @@ -105,7 +120,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 +132,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 +159,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 = arguments(0); + Request request = getArgument(1, Request.class); + String msg = String.valueOf(exception); + return new Object[]{null, msg, request, null, exception}; } }); } @@ -169,50 +185,42 @@ 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); + + IsProperties data = settings.getData(); + if (data != null) { + String dataString = null, contentType = null; + if (data.getDataImpl() instanceof JavaScriptObject && JsUtils.isFormData(data.<JavaScriptObject>getDataImpl())) { + dataString = null; + contentType = FormPanel.ENCODING_URLENCODED; + } else if (settings.getType().matches("(POST|PUT)") && "json".equalsIgnoreCase(settings.getDataType())) { + dataString = data.toJson(); + contentType = JSON_CONTENT_TYPE_UTF8; } else { - data = sdata.toQueryString(); + dataString = data.toQueryString(); + contentType = FormPanel.ENCODING_URLENCODED; } + settings.setDataString(dataString); + settings.setContentType(contentType); } - 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); } @@ -225,7 +233,7 @@ public class Ajax extends GQuery { return ajax(s); } - public static Promise ajax(String url, Properties p) { + public static Promise ajax(String url, IsProperties p) { Settings s = createSettings(); s.load(p); s.setUrl(url); @@ -237,20 +245,31 @@ 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(IsProperties p) { + Settings s = GQ.create(Settings.class); + s.load(p.getDataImpl()); return s; } - public static Promise get(String url, Properties data, Function onSuccess) { + public static Promise get(String url) { + return get(url, null); + } + + public static Promise get(String url, IsProperties data) { + return get(url, (IsProperties)data, null); + } + + public static Promise get(String url, IsProperties data, Function onSuccess) { Settings s = createSettings(); s.setUrl(url); s.setDataType("txt"); @@ -260,7 +279,11 @@ public class Ajax extends GQuery { return ajax(s); } - public static Promise getJSON(String url, Properties data, Function onSuccess) { + public static Promise getJSON(String url, IsProperties data) { + return getJSON(url, data, null); + } + + public static Promise getJSON(String url, IsProperties data, Function onSuccess) { Settings s = createSettings(); s.setUrl(url); s.setDataType("json"); @@ -269,12 +292,16 @@ public class Ajax extends GQuery { s.setSuccess(onSuccess); return ajax(s); } - + public static Promise getJSONP(String url) { - return getJSONP(url, null, null); + return getJSONP(url, null); } - public static Promise getJSONP(String url, Properties data, Function onSuccess) { + public static Promise getJSONP(String url, IsProperties data) { + return getJSONP(url, (IsProperties)data, null); + } + + public static Promise getJSONP(String url, IsProperties data, Function onSuccess) { Settings s = createSettings(); s.setUrl(url); s.setDataType("jsonp"); @@ -327,11 +354,11 @@ public class Ajax extends GQuery { ); } - public static Promise post(String url, Properties data) { - return post(url, data, null); + public static Promise post(String url, IsProperties data) { + return post(url, (IsProperties)data, null); } - - public static Promise post(String url, Properties data, final Function onSuccess) { + + public static Promise post(String url, IsProperties data, final Function onSuccess) { Settings s = createSettings(); s.setUrl(url); s.setDataType("txt"); @@ -345,11 +372,11 @@ public class Ajax extends GQuery { super(gq); } - public Ajax load(String url, Properties data) { + public Ajax load(String url, IsProperties data) { return load(url, data); } - public Ajax load(String url, Properties data, final Function onSuccess) { + public Ajax load(String url, IsProperties data, final Function onSuccess) { Settings s = createSettings(); final String filter = url.contains(" ") ? url.replaceFirst("^[^\\s]+\\s+", "") : ""; s.setUrl(url.replaceAll("\\s+.+$", "")); @@ -363,7 +390,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..12ce7cda --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/ajax/AjaxTransportJs.java @@ -0,0 +1,51 @@ +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.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..41f32b37 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,13 +21,12 @@ 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.IsProperties; 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; import com.google.gwt.query.client.plugins.deferred.Deferred.DeferredPromiseImpl; -import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.xhr.client.ReadyStateChangeHandler; import com.google.gwt.xhr.client.XMLHttpRequest; @@ -36,7 +35,7 @@ import com.google.gwt.xhr.client.XMLHttpRequest; * <pre> * RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "http://127.0.0.1:8888/whatever"); * PromiseRequest gettingResponse = new PromiseReqBuilder(builder); - * + * * gettingResponse.fail(new Function() { * public void f() { * Throwable exception = arguments(0); @@ -49,7 +48,7 @@ import com.google.gwt.xhr.client.XMLHttpRequest; * </pre> */ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCallback { - + public PromiseReqBuilder(RequestBuilder builder) { builder.setCallback(this); try { @@ -58,13 +57,19 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal onError(null, e); } } - + /** * Using this constructor we access to some things in the xmlHttpRequest * 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(); + IsProperties data = settings.getData(); + String ctype = settings.getContentType(); + Boolean isFormData = data != null && data.getDataImpl() instanceof JavaScriptObject && JsUtils.isFormData(data.<JavaScriptObject>getDataImpl()); + XMLHttpRequest xmlHttpRequest = XMLHttpRequest.create(); try { if (settings.getUsername() != null && settings.getPassword() != null) { @@ -80,17 +85,17 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal onError(null, e); return; } - + JsUtils.prop(xmlHttpRequest, "onprogress", JsUtils.wrapFunction(new Function() { public void f() { 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"); } })); - + JavaScriptObject upload = JsUtils.prop(xmlHttpRequest, "upload"); JsUtils.prop(upload, "onprogress", JsUtils.wrapFunction(new Function() { public void f() { @@ -101,35 +106,24 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal dfd.notify(total, loaded, percent, "upload"); } })); - - Properties headers = settings.getHeaders(); + + IsProperties 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)) { xmlHttpRequest.setRequestHeader("Content-Type", ctype); } // Using gQuery to set credentials since this method was added in 2.5.1 // xmlHttpRequest.setWithCredentials(true); - JsUtils.prop(xmlHttpRequest, "withCredentials", true); - + JsUtils.prop(xmlHttpRequest, "withCredentials", settings.getWithCredentials()); + final Request request = createRequestVltr(xmlHttpRequest, settings.getTimeout(), this); - + xmlHttpRequest.setOnReadyStateChange(new ReadyStateChangeHandler() { public void onReadyStateChange(XMLHttpRequest xhr) { if (xhr.getReadyState() == XMLHttpRequest.DONE) { @@ -140,7 +134,7 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal }); try { - JsUtils.runJavascriptFunction(xmlHttpRequest, "send", data); + JsUtils.runJavascriptFunction(xmlHttpRequest, "send", isFormData ? data.getDataImpl() : settings.getDataString()); } catch (JavaScriptException e) { onError(null, e); } @@ -159,14 +153,14 @@ public class PromiseReqBuilder extends DeferredPromiseImpl implements RequestCal dfd.resolve(response, request); } } - + /** * Using violator pattern to execute private method */ private native void fireOnResponseReceivedVltr(Request rq, RequestCallback cb) /*-{ rq.@com.google.gwt.http.client.Request::fireOnResponseReceived(Lcom/google/gwt/http/client/RequestCallback;)(cb); }-*/; - + /** * Using violator pattern to use protected constructor */ 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..270db704 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.IsProperties; 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(IsProperties.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 " + IsProperties.class.getName() + " create(String s) {"); + sw.indent(); + sw.println("return " + Properties.class.getName() + ".create(s);"); + sw.outdent(); + sw.println("}"); + sw.println("public " + IsProperties.class.getName() + " 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..d6f2fcdb --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/AjaxTransportJre.java @@ -0,0 +1,217 @@ +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.IsProperties; +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; + + private static CookieManager cookieManager = CookieManager.getInstance(); + + private static boolean debugOutput = false; + + private static boolean followRedirections = true; + + public static void enableCORS(String domain) { + localDomain = domain; + System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); + } + + public static void enableDebug(boolean b) { + debugOutput = b; + } + + public static void enableCookies(boolean b) { + cookieManager = b ? CookieManager.getInstance() : null; + } + + public static void enableRedirections(boolean b) { + followRedirections = b; + } + + private final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:26.0) Gecko/20100101 Firefox/26.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) { + e.printStackTrace(); + 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.setInstanceFollowRedirects(followRedirections); + + 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())); + } + if (cookieManager != null) { + cookieManager.setCookies(c); + } + + 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()); + } + + IsProperties headers = s.getHeaders(); + if (headers != null) { + for (String h : headers.getFieldNames()) { + c.setRequestProperty(h, "" + headers.get(h)); + } + } + + if (s.getType().matches("POST|PUT")) { + c.setRequestProperty("Content-Type", s.getContentType()); + + debugRequest(c, s.getDataString()); + + c.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(c.getOutputStream()); + wr.writeBytes(s.getDataString()); + wr.flush(); + wr.close(); + } else { + debugRequest(c, null); + } + + int code = c.getResponseCode(); + if (isCORS) { + if (!localDomain.equals(c.getHeaderField("Access-Control-Allow-Origin"))) { + code = 0; + } + if (s.getWithCredentials() && c.getHeaderField("Access-Control-Allow-Credentials") == null) { + 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(); + + if (cookieManager != null) { + cookieManager.storeCookies(c); + } + + return new ResponseJre(code, c.getResponseMessage(), response.toString(), c.getHeaderFields()); + } + + private void debugRequest(HttpURLConnection c, String payload) { + if (debugOutput) { + System.out.println(c.getRequestMethod() + " " + c.getURL().getPath()); + for (String s : c.getRequestProperties().keySet()) { + String v = c.getRequestProperties().get(s).get(0); + if ("Cookie".equals(s)) { + System.out.println(s + ":"); + for (String y : v.split("; ")) { + System.out.println(" " + y); + } + } else { + System.out.println(s + ": " + v); + } + } + if (payload != null) { + for (String y : payload.split("&")) { + System.out.println(" " + y); + } + } + System.out.println(""); + } + } +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/vm/CookieManager.java b/gwtquery-core/src/main/java/com/google/gwt/query/vm/CookieManager.java new file mode 100644 index 00000000..1f1241ba --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/CookieManager.java @@ -0,0 +1,224 @@ +package com.google.gwt.query.vm; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * @author Ian Brown spam@hccp.org + * http://www.hccp.org/java-net-cookie-how-to.html + */ +public class CookieManager { + + private Map<String,Map<String,Map<String, String>>> store = new HashMap<String, Map<String,Map<String, String>>>(); + + private static final String SET_COOKIE = "Set-Cookie"; + private static final String COOKIE_VALUE_DELIMITER = ";"; + private static final String PATH = "path"; + private static final String EXPIRES = "expires"; + private static final String DATE_FORMAT = "EEE, dd-MMM-yyyy hh:mm:ss z"; + private static final String SET_COOKIE_SEPARATOR = "; "; + private static final String COOKIE = "Cookie"; + + private static final char NAME_VALUE_SEPARATOR = '='; + private static final char DOT = '.'; + + private DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);; + + private static CookieManager cookieManager = new CookieManager(); + + public static CookieManager getInstance() { + return cookieManager; + } + + public void clear() { + store.clear(); + } + + public void removeDomainCookies(String domain) { + store.remove(domain); + } + + public void removeDomainCookie(String domain, String... cookies) { + Map<String, Map<String, String>> domainStore = store.get(domain); + if (domainStore != null) { + for (String cookie: cookies) { + domainStore.remove(cookie); + } + } + } + + public void setDomcainCookie(String host, String name, String value) { + setDomcainCookieProperty(host, name, name, value); + } + + public void setDomcainCookieProperty(String host, String name, String prop, String value) { + String domain = getDomainFromHost(host); + Map<String, Map<String, String>> domainStore = store.get(domain); + if (domainStore == null) { + domainStore = new HashMap<String, Map<String,String>>(); + store.put(domain, domainStore); + } + Map<String, String> cookie = domainStore.get(name); + if (cookie == null) { + cookie = new HashMap<String, String>(); + domainStore.put(name, cookie); + } + if (value == null) { + cookie.remove(prop); + } else { + cookie.put(prop, value); + } + } + + /** + * Retrieves and stores cookies returned by the host on the other side of the the open + * java.net.URLConnection. + * + * The connection MUST have been opened using the connect() method or a IOException will be + * thrown. + * + * @param conn a java.net.URLConnection - must be open, or IOException will be thrown + * @throws java.io.IOException Thrown if conn is not open. + */ + public void storeCookies(URLConnection conn) throws IOException { + // let's determine the domain from where these cookies are being sent + String domain = getDomainFromHost(conn.getURL().getHost()); + + Map<String,Map<String, String>> domainStore; // this is where we will store cookies for this domain + + // now let's check the store to see if we have an entry for this domain + if (store.containsKey(domain)) { + // we do, so lets retrieve it from the store + domainStore = store.get(domain); + } else { + // we don't, so let's create it and put it in the store + domainStore = new HashMap<String, Map<String,String>>(); + store.put(domain, domainStore); + } + + // OK, now we are ready to get the cookies out of the URLConnection + + String headerName = null; + for (int i = 1; (headerName = conn.getHeaderFieldKey(i)) != null; i++) { + if (headerName.equalsIgnoreCase(SET_COOKIE)) { + Map<String, String> cookie = new HashMap<String, String>(); + StringTokenizer st = new StringTokenizer(conn.getHeaderField(i), COOKIE_VALUE_DELIMITER); + + // the specification dictates that the first name/value pair + // in the string is the cookie name and value, so let's handle + // them as a special case: + + if (st.hasMoreTokens()) { + String token = st.nextToken(); + String name = token.substring(0, token.indexOf(NAME_VALUE_SEPARATOR)); + String value = token.substring(token.indexOf(NAME_VALUE_SEPARATOR) + 1, token.length()); + domainStore.put(name, cookie); + cookie.put(name, value); + } + + while (st.hasMoreTokens()) { + String token = st.nextToken().toLowerCase(); + int idx = token.indexOf(NAME_VALUE_SEPARATOR); + if (idx > 0 && idx < token.length() -1) { + cookie.put(token.substring(0, idx).toLowerCase(), token.substring(idx + 1, token.length())); + } + } + } + } + } + + /** + * Prior to opening a URLConnection, calling this method will set all unexpired cookies that match + * the path or subpaths for thi underlying URL + * + * The connection MUST NOT have been opened method or an IOException will be thrown. + * + * @param conn a java.net.URLConnection - must NOT be open, or IOException will be thrown + * @throws java.io.IOException Thrown if conn has already been opened. + */ + public void setCookies(URLConnection conn) throws IOException { + + // let's determine the domain and path to retrieve the appropriate cookies + URL url = conn.getURL(); + String domain = getDomainFromHost(url.getHost()); + if (domain.equals("localhost")) { + domain = "linkedin.com"; + } + String path = url.getPath(); + + Map<String, Map<String, String>> domainStore = store.get(domain); + if (domainStore == null) + return; + StringBuffer cookieStringBuffer = new StringBuffer(); + + Iterator<String> cookieNames = domainStore.keySet().iterator(); + while (cookieNames.hasNext()) { + String cookieName = cookieNames.next(); + Map<String, String> cookie = domainStore.get(cookieName); + // check cookie to ensure path matches and cookie is not expired + // if all is cool, add cookie to header string + if (comparePaths((String) cookie.get(PATH), path) + && isNotExpired(cookie.get(EXPIRES))) { + cookieStringBuffer.append(cookieName); + cookieStringBuffer.append("="); + cookieStringBuffer.append(cookie.get(cookieName)); + if (cookieNames.hasNext()) + cookieStringBuffer.append(SET_COOKIE_SEPARATOR); + } + } + try { + conn.setRequestProperty(COOKIE, cookieStringBuffer.toString()); + } catch (java.lang.IllegalStateException ise) { + IOException ioe = + new IOException( + "Illegal State! Cookies cannot be set on a URLConnection that is already connected. " + + "Only call setCookies(java.net.URLConnection) AFTER calling java.net.URLConnection.connect()."); + throw ioe; + } + } + + private String getDomainFromHost(String host) { + host = host.toLowerCase().replaceFirst("https?://", "").replaceAll("[/?:].*$", ""); + if (host.indexOf(DOT) != host.lastIndexOf(DOT)) { + return host.substring(host.indexOf(DOT) + 1); + } else { + return host; + } + } + + private boolean isNotExpired(String cookieExpires) { + if (cookieExpires == null) + return true; + Date now = new Date(); + try { + return (now.compareTo(dateFormat.parse(cookieExpires))) <= 0; + } catch (java.text.ParseException pe) { + pe.printStackTrace(); + return false; + } + } + + private boolean comparePaths(String cookiePath, String targetPath) { + if (cookiePath == null) { + return true; + } else if (cookiePath.equals("/")) { + return true; + } else if (targetPath.regionMatches(0, cookiePath, 0, cookiePath.length())) { + return true; + } else { + return false; + } + } + + public String toString() { + return store.toString(); + } +} 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..80881507 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java @@ -0,0 +1,306 @@ +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.IsProperties; +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 (IsProperties.class.isAssignableFrom(clz) && !clz.isAssignableFrom(ret.getClass())) { + ret = jsonFactory.create(clz, (JSONObject)ret); + } + } + // Javascript always returns a double + if (ret instanceof Number) { + ret = Double.valueOf(((Number) ret).doubleValue()); + } + } + } 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 IsProperties) { + return obj != null ? obj.put(attr, ((IsProperties) o).getDataImpl()) : arr.put(((IsProperties) o).getDataImpl()); + } 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|getDataImpl")) { + 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 == 2 && mname.equals("set")) { + setValue(null, jsonObject, String.valueOf(args[0]), args[1], method); + return proxy; + } 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 (!"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 IsProperties createBinder() { + InvocationHandler handler = new JsonBuilderHandler(); + return (IsProperties)Proxy.newProxyInstance(IsProperties.class.getClassLoader(), new Class[] {IsProperties.class}, handler); + } + + public IsProperties createBinder(JSONObject jso) { + InvocationHandler handler = new JsonBuilderHandler(jso); + return (IsProperties)Proxy.newProxyInstance(IsProperties.class.getClassLoader(), new Class[] {IsProperties.class}, handler); + } + + @Override + public IsProperties create(String s) { + IsProperties ret = createBinder(); + ret.parse(Properties.wrapPropertiesString(s)); + return ret; + } + + @Override + public IsProperties 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..207484a9 --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/ResponseJre.java @@ -0,0 +1,70 @@ +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() { + String ret = ""; + for (Header h : getHeaders()) { + ret += h.getName() + ":" + h.getValue() + "\n"; + } + return ret; + } + 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..7f8fb42e --- /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.IsProperties; +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 IsProperties create(String s) { + return getFactory().create(s); + } + + public static IsProperties 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..1167651d --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java @@ -0,0 +1,104 @@ +/* + * 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..f5d0cbf5 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java @@ -0,0 +1,296 @@ +/* + * 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 junit.framework.Assert; + +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.IsProperties; +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 IsProperties 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() { + IsProperties 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) + .done(new Function() { + public void f() { + Response r = arguments(3); + Assert.assertNotNull(r.getHeader("Access-Control-Allow-Origin")); + Assert.assertNull(r.getHeader("Access-Control-Allow-Credentials")); + } + }); + } + + @DoNotRunWith(Platform.HtmlUnitBug) + public void testAjaxJsonGet_CORS_WithCredentials_Supported() { + Settings s = Ajax.createSettings() + .setType("get") + // Enable credentials in servlet + .setUrl(echoUrlCORS + "&credentials=true") + .setData(jsonGET) + .setDataType("json") + .setWithCredentials(true); + + performAjaxJsonTest_CORS(s) + .done(new Function() { + public void f() { + Response r = arguments(3); + Assert.assertNotNull(r.getHeader("Access-Control-Allow-Origin")); + Assert.assertNotNull(r.getHeader("Access-Control-Allow-Credentials")); + } + }); + } + + @DoNotRunWith(Platform.HtmlUnitBug) + public void testAjaxJsonGet_CORS_WithCredentials_Unsupported() { + Settings s = Ajax.createSettings() + .setType("get") + // Disable credentials in servlet + .setUrl(echoUrlCORS) + .setData(jsonGET) + .setDataType("json") + .setWithCredentials(true); + + Ajax.ajax(s) + .fail(finishFunction) + .done(failFunction); + } + + 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() { + IsProperties 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.<IsProperties>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..ac648fc1 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java @@ -0,0 +1,121 @@ +/* + * 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 { + public static enum Type {BIG, SMALL} + + Date getDate(); + void setDate(Date d); + Type getType(); + void setType(Type t); + } + + 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..b00d2469 --- /dev/null +++ b/gwtquery-core/src/test/java/com/google/gwt/query/servlet/GQAjaxTestServlet.java @@ -0,0 +1,85 @@ +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; + +import com.google.gwt.query.client.plugins.ajax.Ajax; + +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(name + "sleeping: " + ms); + Thread.sleep(ms); + } catch (Exception e) { + } + 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() != null + && req.getContentType().toLowerCase().startsWith(Ajax.JSON_CONTENT_TYPE)) { + 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); + if ("true".equals(req.getParameter("credentials"))) { + 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); + } +} |