Merging releases/1.5 into trunk svn merge -r3505:3549 https://google-web-toolkit.googlecode.com/svn/releases/1.5 . git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3589 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java index 726d7f4..01800bc 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -1240,7 +1240,7 @@ for (JStatement statement : body.statements) { if (statement instanceof JCaseStatement) { potentialNoOpCaseStatements.add(statement); - } else if (isUnconditionalBreak(statement)) { + } else if (isUnconditionalUnlabeledBreak(statement)) { // If we have any potential no-ops, they now become real no-ops. noOpCaseStatements.addAll(potentialNoOpCaseStatements); potentialNoOpCaseStatements.clear();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java index 4f9a305..b284fad 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -189,6 +189,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; +import java.util.TreeSet; /** * This is the big kahuna where most of the nitty gritty of creating our AST @@ -2553,7 +2555,7 @@ return null; } else { // look for a method - String almostMatches = null; + TreeSet<String> almostMatches = new TreeSet<String>(); String methodName = parsed.memberName(); String jsniSig = parsed.memberSignature(); if (type == null) { @@ -2561,31 +2563,44 @@ return program.getNullMethod(); } } else { - for (int i = 0; i < type.methods.size(); ++i) { - JMethod method = type.methods.get(i); - if (method.getName().equals(methodName)) { - String sig = JProgram.getJsniSig(method); - if (sig.equals(jsniSig)) { - return method; - } else if (almostMatches == null) { - almostMatches = "'" + sig + "'"; - } else { - almostMatches += ", '" + sig + "'"; + Queue<JReferenceType> workList = new LinkedList<JReferenceType>(); + workList.add(type); + while (!workList.isEmpty()) { + JReferenceType cur = workList.poll(); + for (int i = 0; i < cur.methods.size(); ++i) { + JMethod method = cur.methods.get(i); + if (method.getName().equals(methodName)) { + String sig = JProgram.getJsniSig(method); + if (sig.equals(jsniSig)) { + return method; + } else { + almostMatches.add(sig); + } } } + if (cur.extnds != null) { + workList.add(cur.extnds); + } + workList.addAll(cur.implments); } } - if (almostMatches == null) { + if (almostMatches.isEmpty()) { reportJsniError(info, methodDecl, "Unresolvable native reference to method '" + methodName + "' in type '" + className + "'"); return null; } else { + StringBuilder suggestList = new StringBuilder(); + String comma = ""; + for (String almost : almostMatches) { + suggestList.append(comma + "'" + almost + "'"); + comma = ", "; + } reportJsniError(info, methodDecl, "Unresolvable native reference to method '" + methodName + "' in type '" + className + "' (did you mean " - + almostMatches + "?)"); + + suggestList.toString() + "?)"); return null; } } @@ -2638,7 +2653,8 @@ private void processMethod(JsNameRef nameRef, SourceInfo info, JMethod method, JsContext<JsExpression> ctx) { - if (method.getEnclosingType() != null) { + JReferenceType enclosingType = method.getEnclosingType(); + if (enclosingType != null) { if (method.isStatic() && nameRef.getQualifier() != null) { reportJsniError(info, methodDecl, "Cannot make a qualified reference to the static method " @@ -2647,6 +2663,16 @@ reportJsniError(info, methodDecl, "Cannot make an unqualified reference to the instance method " + method.getName()); + } else if (!method.isStatic() + && program.isJavaScriptObject(enclosingType)) { + reportJsniError( + info, + methodDecl, + "Illegal reference to instance method '" + + method.getName() + + "' in type '" + + enclosingType.getName() + + "', which is an overlay type; only static references to overlay types are allowed from JSNI"); } } if (ctx.isLvalue()) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java b/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java index 9c401c5..a17dbc4 100644 --- a/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java +++ b/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java
@@ -63,9 +63,11 @@ } private void addMember(Member member, String sig) { - memberById.add(member); - int index = memberById.size() - 1; - memberIdByName.put(sig, new Integer(index)); + if (!memberIdByName.containsKey(sig)) { + memberById.add(member); + int index = memberById.size() - 1; + memberIdByName.put(sig, new Integer(index)); + } } private String getJsniSignature(Member member) { @@ -151,6 +153,9 @@ if (superclass != null) { lazyInitTargetMembersUsingReflectionHelper(superclass, false); } + for (Class<?> intf : targetClass.getInterfaces()) { + lazyInitTargetMembersUsingReflectionHelper(intf, false); + } if (addConstructors) { Constructor<?>[] constructors = targetClass.getDeclaredConstructors();
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java index 022713c..0ebbe02 100644 --- a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java +++ b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
@@ -44,7 +44,6 @@ import java.net.ServerSocket; import java.net.URISyntaxException; import java.net.URL; -import java.net.URLConnection; import java.util.Collections; import java.util.Map; import java.util.Map.Entry;
diff --git a/user/javadoc/com/google/gwt/examples/HistoryExample.java b/user/javadoc/com/google/gwt/examples/HistoryExample.java index dbe83f9..99f3d0f 100644 --- a/user/javadoc/com/google/gwt/examples/HistoryExample.java +++ b/user/javadoc/com/google/gwt/examples/HistoryExample.java
@@ -33,15 +33,12 @@ Hyperlink link1 = new Hyperlink("link to bar", "bar"); Hyperlink link2 = new Hyperlink("link to baz", "baz"); - // If the application starts with no history token, start it off in the + // If the application starts with no history token, redirect to a new // 'baz' state. String initToken = History.getToken(); - if (initToken.length() == 0) - initToken = "baz"; - - // onHistoryChanged() is not called when the application first runs. Call - // it now in order to reflect the initial state. - onHistoryChanged(initToken); + if (initToken.length() == 0) { + History.newItem("baz"); + } // Add widgets to the root panel. VerticalPanel panel = new VerticalPanel(); @@ -53,6 +50,9 @@ // Add history listener History.addHistoryListener(this); + + // Now that we've setup our listener, fire the initial history state. + History.fireCurrentHistoryState(); } public void onHistoryChanged(String historyToken) {
diff --git a/user/src/com/google/gwt/core/client/JavaScriptException.java b/user/src/com/google/gwt/core/client/JavaScriptException.java index b4e45d7..8bb9b72 100644 --- a/user/src/com/google/gwt/core/client/JavaScriptException.java +++ b/user/src/com/google/gwt/core/client/JavaScriptException.java
@@ -62,10 +62,18 @@ */ private static native String getProperties0(JavaScriptObject e) /*-{ var result = ""; - for (prop in e) { - if (prop != "name" && prop != "message") { - result += "\n " + prop + ": " + e[prop]; + try { + for (prop in e) { + if (prop != "name" && prop != "message" && prop != "toString") { + try { + result += "\n " + prop + ": " + e[prop]; + } catch (ignored) { + // Skip the property if it threw an exception. + } + } } + } catch (ignored) { + // If we can't do "in" on the exception, just return what we have. } return result; }-*/;
diff --git a/user/src/com/google/gwt/dom/client/HeadingElement.java b/user/src/com/google/gwt/dom/client/HeadingElement.java index 45030b8..a21532f 100644 --- a/user/src/com/google/gwt/dom/client/HeadingElement.java +++ b/user/src/com/google/gwt/dom/client/HeadingElement.java
@@ -48,7 +48,7 @@ assert tag.length() == 2; assert tag.charAt(0) == 'h'; - int n = Integer.parseInt(tag.substring(1, 1)); + int n = Integer.parseInt(tag.substring(1, 2)); assert (n >= 1) && (n <= 6); }
diff --git a/user/src/com/google/gwt/user/RemoteService.gwt.xml b/user/src/com/google/gwt/user/RemoteService.gwt.xml index e03d3c4..2c9a680 100644 --- a/user/src/com/google/gwt/user/RemoteService.gwt.xml +++ b/user/src/com/google/gwt/user/RemoteService.gwt.xml
@@ -31,19 +31,11 @@ <!-- Declare a property to determine whether warnings for final instance fields should be suppressed. - - NOTE: We no longer emit warnings for final fields. This property has - been deprecated, is currently being ignored, and will be removed in a - future version of GWT. --> <define-property name="gwt.suppressNonStaticFinalFieldWarnings" values="true,false" /> <!-- Default warning for non-static, final fields enabled - - NOTE: We no longer emit a warning for final fields. This property has - been deprecated, is currently being ignored, and will be removed in a - future version of GWT. --> <set-property name="gwt.suppressNonStaticFinalFieldWarnings" value="false" />
diff --git a/user/src/com/google/gwt/user/client/DOM.java b/user/src/com/google/gwt/user/client/DOM.java index f931cbe..b7865d5 100644 --- a/user/src/com/google/gwt/user/client/DOM.java +++ b/user/src/com/google/gwt/user/client/DOM.java
@@ -401,14 +401,8 @@ * * @param evt the event to be tested * @return <code>true</code> if ALT was depressed when the event occurred - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or - * {@link Event#ONCONTEXTMENU} */ - public static boolean eventGetAltKey(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.KEYEVENTS | Event.ONCONTEXTMENU, "altKey"); + public static boolean eventGetAltKey(Event evt) { return impl.eventGetAltKey(evt); } @@ -418,11 +412,8 @@ * @param evt the event to be tested * @return a bit-field, defined by {@link Event#BUTTON_LEFT}, * {@link Event#BUTTON_MIDDLE}, and {@link Event#BUTTON_RIGHT} - * @throws AssertionError if event type is not one of - * {@link Event#ONMOUSEDOWN} or {@link Event#ONMOUSEUP} */ - public static int eventGetButton(Event evt) throws AssertionError { - assertEventType(evt, Event.ONMOUSEDOWN | Event.ONMOUSEUP, "button"); + public static int eventGetButton(Event evt) { return impl.eventGetButton(evt); } @@ -431,14 +422,8 @@ * * @param evt the event to be tested * @return the mouse x-position - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or - * {@link Event#ONCONTEXTMENU} */ - public static int eventGetClientX(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.ONMOUSEWHEEL | Event.ONCONTEXTMENU, "clientX"); + public static int eventGetClientX(Event evt) { return impl.eventGetClientX(evt); } @@ -447,14 +432,8 @@ * * @param evt the event to be tested * @return the mouse y-position - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or - * {@link Event#ONCONTEXTMENU} */ - public static int eventGetClientY(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.ONMOUSEWHEEL | Event.ONCONTEXTMENU, "clientY"); + public static int eventGetClientY(Event evt) { return impl.eventGetClientY(evt); } @@ -463,14 +442,8 @@ * * @param evt the event to be tested * @return <code>true</code> if CTRL was depressed when the event occurred - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or - * {@link Event#ONCONTEXTMENU} */ - public static boolean eventGetCtrlKey(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.KEYEVENTS | Event.ONCONTEXTMENU, "ctrlKey"); + public static boolean eventGetCtrlKey(Event evt) { return impl.eventGetCtrlKey(evt); } @@ -503,11 +476,8 @@ * * @param evt the event to be tested * @return the element from which the mouse pointer was moved - * @throws AssertionError if event type is not one of - * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT} */ - public static Element eventGetFromElement(Event evt) throws AssertionError { - assertEventType(evt, Event.ONMOUSEOVER | Event.ONMOUSEOUT, "fromElement"); + public static Element eventGetFromElement(Event evt) { return impl.eventGetFromElement(evt); } @@ -522,11 +492,9 @@ * * @param evt the event to be tested * @return the Unicode character or key code. - * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS} * @see com.google.gwt.user.client.ui.KeyboardListener */ - public static int eventGetKeyCode(Event evt) throws AssertionError { - assertEventType(evt, Event.KEYEVENTS, "keyCode"); + public static int eventGetKeyCode(Event evt) { return impl.eventGetKeyCode(evt); } @@ -535,14 +503,8 @@ * * @param evt the event to be tested * @return <code>true</code> if META was depressed when the event occurred - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or - * {@link Event#ONCONTEXTMENU} */ - public static boolean eventGetMetaKey(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.KEYEVENTS | Event.ONCONTEXTMENU, "metaKey"); + public static boolean eventGetMetaKey(Event evt) { return impl.eventGetMetaKey(evt); } @@ -560,11 +522,8 @@ * * @param evt the event to be examined. * @return The velocity of the mouse wheel. - * @throws AssertionError if event type is not {@link Event#ONMOUSEWHEEL} */ - public static int eventGetMouseWheelVelocityY(Event evt) - throws AssertionError { - assertEventType(evt, Event.ONMOUSEWHEEL, "mouseWheelVelocityY"); + public static int eventGetMouseWheelVelocityY(Event evt) { return impl.eventGetMouseWheelVelocityY(evt); } @@ -573,10 +532,8 @@ * * @param evt the event to be tested * @return <code>true</code> if this key event was an auto-repeat - * @throws AssertionError if event type is not {@link Event#ONKEYDOWN} */ - public static boolean eventGetRepeat(Event evt) throws AssertionError { - assertEventType(evt, Event.ONKEYDOWN, "repeat"); + public static boolean eventGetRepeat(Event evt) { return impl.eventGetRepeat(evt); } @@ -585,14 +542,8 @@ * * @param evt the event to be tested * @return the mouse x-position - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL}, - * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or - * {@link Event#ONCONTEXTMENU} */ - public static int eventGetScreenX(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.ONCLICK - | Event.ONDBLCLICK | Event.ONCONTEXTMENU, "screenX"); + public static int eventGetScreenX(Event evt) { return impl.eventGetScreenX(evt); } @@ -601,14 +552,8 @@ * * @param evt the event to be tested * @return the mouse y-position - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL}, - * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or - * {@link Event#ONCONTEXTMENU} */ - public static int eventGetScreenY(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.ONCLICK - | Event.ONDBLCLICK | Event.ONCONTEXTMENU, "screenY"); + public static int eventGetScreenY(Event evt) { return impl.eventGetScreenY(evt); } @@ -617,14 +562,8 @@ * * @param evt the event to be tested * @return <code>true</code> if shift was depressed when the event occurred - * @throws AssertionError if event type is not one of - * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK}, - * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or - * {@link Event#ONCONTEXTMENU} */ - public static boolean eventGetShiftKey(Event evt) throws AssertionError { - assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK - | Event.KEYEVENTS | Event.ONCONTEXTMENU, "shiftKey"); + public static boolean eventGetShiftKey(Event evt) { return impl.eventGetShiftKey(evt); } @@ -644,11 +583,8 @@ * * @param evt the event to be tested * @return the element to which the mouse pointer was moved - * @throws AssertionError if event type is not one of - * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT} */ - public static Element eventGetToElement(Event evt) throws AssertionError { - assertEventType(evt, Event.ONMOUSEOVER | Event.ONMOUSEOUT, "toElement"); + public static Element eventGetToElement(Event evt) { return impl.eventGetToElement(evt); } @@ -686,10 +622,8 @@ * * @param evt the event whose key code is to be set * @param key the new key code - * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS} */ - public static void eventSetKeyCode(Event evt, char key) throws AssertionError { - assertEventType(evt, Event.KEYEVENTS, "keyCode"); + public static void eventSetKeyCode(Event evt, char key) { impl.eventSetKeyCode(evt, key); } @@ -1347,20 +1281,6 @@ return ret; } - /** - * Assert that the event is of the given event type, as defined by the - * {@link Event} class. - * - * @param evt the {@link Event} to check - * @param evtType the event type that is expected - * @param attr the attribute that should be defined by the event - */ - private static void assertEventType(Event evt, int evtType, String attr) { - assert (eventGetType(evt) & evtType) != 0 : - "attribute '" + attr + "' not defined for event type '" - + eventGetTypeString(evt) + "'"; - } - private static void dispatchEventAndCatch(Event evt, Element elem, EventListener listener, UncaughtExceptionHandler handler) { try {
diff --git a/user/src/com/google/gwt/user/client/History.java b/user/src/com/google/gwt/user/client/History.java index ff8d1e6..d3e0612 100644 --- a/user/src/com/google/gwt/user/client/History.java +++ b/user/src/com/google/gwt/user/client/History.java
@@ -40,10 +40,10 @@ * <p> * <h3>URL Encoding</h3> * Any valid characters may be used in the history token and will survive - * round-trips through newItem to getToken()/onHistoryChanged(), but most will - * be encoded in the user-visible URL. The following US-ASCII characters are not - * encoded on any currently supported browser (but may be in the future due to - * future browser changes): + * round-trips through {@link #newItem(String)} to {@link #getToken()}/{@link HistoryListener#onHistoryChanged(String)}, + * but most will be encoded in the user-visible URL. The following US-ASCII + * characters are not encoded on any currently supported browser (but may be in + * the future due to future browser changes): * <ul> * <li>a-z * <li>A-Z @@ -63,12 +63,11 @@ impl = null; // Tell the user. - GWT.log( - "Unable to initialize the history subsystem; did you " - + "include the history frame in your host page? Try " - + "<iframe src=\"javascript:''\" id='__gwt_historyFrame' " - + "style='position:absolute;width:0;height:0;border:0'>" - + "</iframe>", null); + GWT.log("Unable to initialize the history subsystem; did you " + + "include the history frame in your host page? Try " + + "<iframe src=\"javascript:''\" id='__gwt_historyFrame' " + + "style='position:absolute;width:0;height:0;border:0'>" + + "</iframe>", null); } } @@ -91,6 +90,16 @@ }-*/; /** + * Fire {@link HistoryListener#onHistoryChanged(String)} events with the + * current history state. This is most often called at the end of an + * application's {@link com.google.gwt.core.client.EntryPoint#onModuleLoad()} + * to inform history listeners of the initial application state. + */ + public static void fireCurrentHistoryState() { + HistoryImpl.fireHistoryChangedImpl(getToken()); + } + + /** * Programmatic equivalent to the user pressing the browser's 'forward' * button. */ @@ -99,11 +108,11 @@ }-*/; /** - * Gets the current history token. The listener will not receive an - * onHistoryChanged() event for the initial token; requiring that an - * application request the token explicitly on startup gives it an opportunity - * to run different initialization code in the presence or absence of an - * initial token. + * Gets the current history token. The listener will not receive a + * {@link HistoryListener#onHistoryChanged(String)} event for the initial + * token; requiring that an application request the token explicitly on + * startup gives it an opportunity to run different initialization code in the + * presence or absence of an initial token. * * @return the initial token, or the empty string if none is present. */ @@ -114,8 +123,8 @@ /** * Adds a new browser history entry. In hosted mode, the 'back' and 'forward' * actions are accessible via the standard Alt-Left and Alt-Right keystrokes. - * Calling this method will cause {@link HistoryListener#onHistoryChanged} to - * be called as well. + * Calling this method will cause + * {@link HistoryListener#onHistoryChanged(String)} to be called as well. * * @param historyToken the token to associate with the new history item */ @@ -126,11 +135,14 @@ /** * Adds a new browser history entry. In hosted mode, the 'back' and 'forward' * actions are accessible via the standard Alt-Left and Alt-Right keystrokes. - * Calling this method will cause {@link HistoryListener#onHistoryChanged} to - * be called as well if and only if issueEvent is true. + * Calling this method will cause + * {@link HistoryListener#onHistoryChanged(String)} to be called as well if + * and only if issueEvent is true. * * @param historyToken the token to associate with the new history item - * @param issueEvent true if an onHistoryChanged event should be issued + * @param issueEvent true if a + * {@link HistoryListener#onHistoryChanged(String)} event should be + * issued */ public static void newItem(String historyToken, boolean issueEvent) { if (impl != null) { @@ -139,6 +151,22 @@ } /** + * Call all history listeners with the specified token. Note that this does + * not change the history system's idea of the current state and is only kept + * for backward compatibility. To fire history events for the initial state of + * the application, instead call {@link #fireCurrentHistoryState()} from the + * application {@link com.google.gwt.core.client.EntryPoint#onModuleLoad()} + * method. + * + * @param historyToken history token to fire events for + * @deprecated Use {@link #fireCurrentHistoryState()} instead. + */ + @Deprecated + public static void onHistoryChanged(String historyToken) { + HistoryImpl.fireHistoryChangedImpl(historyToken); + } + + /** * Removes a history listener. * * @param listener the listener to be removed
diff --git a/user/src/com/google/gwt/user/client/Window.java b/user/src/com/google/gwt/user/client/Window.java index 58e270f..d22e2ff 100644 --- a/user/src/com/google/gwt/user/client/Window.java +++ b/user/src/com/google/gwt/user/client/Window.java
@@ -366,7 +366,7 @@ /** * Opens a new browser window. The "name" and "features" arguments are * specified <a href= - * 'http://www.mozilla.org/docs/dom/domref/dom_window_ref76.html'>here</a>. + * 'http://developer.mozilla.org/en/docs/DOM:window.open'>here</a>. * * @param url the URL that the new window will display * @param name the name of the window (e.g. "_blank")
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java index a16ef2a..a1a1147 100644 --- a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java +++ b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
@@ -40,6 +40,23 @@ historyListeners.add(listener); } + /** + * Fires the {@link HistoryListener#onHistoryChanged(String)} event to all + * listeners with the given token. + */ + public static void fireHistoryChangedImpl(String historyToken) { + // TODO: replace this copy when a more general solution to event handlers + // wanting to remove themselves from the listener list is implemented. + + // This is necessary to avoid a CurrentModificationException in hosted + // mode, as the listeners may try to remove themselves from the list while + // it is being iterated, such as in HistoryTest. + HistoryListener[] listenersToInvoke = historyListeners.toArray(new HistoryListener[historyListeners.size()]); + for (HistoryListener listener : listenersToInvoke) { + listener.onHistoryChanged(historyToken); + } + } + public static native String getToken() /*-{ return $wnd.__gwt_historyToken || ""; }-*/; @@ -75,19 +92,6 @@ } } - private static void fireHistoryChangedImpl(String historyToken) { - // TODO: replace this copy when a more general solution to event handlers - // wanting to remove themselves from the listener list is implemented. - - // This is necessary to avoid a CurrentModificationException in hosted - // mode, as the listeners may try to remove themselves from the list while - // it is being iterated, such as in HistoryTest. - HistoryListener[] listenersToInvoke = historyListeners.toArray(new HistoryListener[historyListeners.size()]); - for (HistoryListener listener : listenersToInvoke) { - listener.onHistoryChanged(historyToken); - } - } - public abstract boolean init(); public final void newItem(String historyToken, boolean issueEvent) {
diff --git a/user/src/com/google/gwt/user/client/rpc/AsyncCallback.java b/user/src/com/google/gwt/user/client/rpc/AsyncCallback.java index ee958d6..67ccdcd 100644 --- a/user/src/com/google/gwt/user/client/rpc/AsyncCallback.java +++ b/user/src/com/google/gwt/user/client/rpc/AsyncCallback.java
@@ -27,7 +27,8 @@ * <p> * Each callable asynchronous method corresponds to a method in the correlated * service interface. The asynchronous method always takes an - * <code>AsyncCallback</code> as its last parameter. + * <code>AsyncCallback<T></code> as its last parameter, where + * <code>T</code> is the return type of the correlated synchronous method. * </p> * * <p> @@ -41,7 +42,7 @@ * Its asynchronous counterpart method be declared as: * * <pre> - * void getShapes(String databaseName, AsyncCallback callback); + * void getShapes(String databaseName, AsyncCallback<Shape[]> callback); * </pre> * * Note that <code>throws</code> declaration is not repeated in the async @@ -53,11 +54,10 @@ * this: * * <pre class="code"> - * service.getShapes(dbName, new AsyncCallback() { - * public void onSuccess(Object result) { + * service.getShapes(dbName, new AsyncCallback<Shape[]>() { + * public void onSuccess(Shape[] result) { * // It's always safe to downcast to the known return type. - * Shape[] shapes = (Shape[]) result; - * controller.processShapes(shapes); + * controller.processShapes(result); * } * * public void onFailure(Throwable caught) { @@ -82,7 +82,12 @@ * * </p> * - * @param <T> + * @param <T> The type of the return value that was declared in the synchronous + * version of the method. If the return type is a primitive, use the + * boxed version of that primitive (for example, an <code>int</code> + * return type becomes an {@link Integer} type argument, and a + * <code>void</code> return type becomes a {@link Void} type + * argument, which is always <code>null</code>). */ public interface AsyncCallback<T> { @@ -103,12 +108,9 @@ void onFailure(Throwable caught); /** - * Called when an asynchronous call completes successfully. It is always safe - * to downcast the parameter (of type <code>Object</code>) to the return - * type of the original method for which this is a callback. Note that if the - * return type of the synchronous service interface method is a primitive then - * the parameter will be the boxed version of the primitive (for example, an - * <code>int</code> return type becomes an {@link Integer}. + * Called when an asynchronous call completes successfully. + * + * @param result the return value of the remote produced call */ void onSuccess(T result); }
diff --git a/user/src/com/google/gwt/user/client/ui/DeckPanel.java b/user/src/com/google/gwt/user/client/ui/DeckPanel.java index 9d65a5d..b0c5e8a 100644 --- a/user/src/com/google/gwt/user/client/ui/DeckPanel.java +++ b/user/src/com/google/gwt/user/client/ui/DeckPanel.java
@@ -148,10 +148,12 @@ int deckHeight = deckElem.getOffsetHeight(); if (growing) { fixedHeight = container2.getOffsetHeight(); - container2.getStyle().setPropertyPx("height", fixedHeight - 1); + container2.getStyle().setPropertyPx("height", + Math.max(1, fixedHeight - 1)); } else { fixedHeight = container1.getOffsetHeight(); - container1.getStyle().setPropertyPx("height", fixedHeight - 1); + container1.getStyle().setPropertyPx("height", + Math.max(1, fixedHeight - 1)); } if (deckElem.getOffsetHeight() != deckHeight) { fixedHeight = -1;
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java index a8f599d..26b12a7 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java +++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
@@ -19,7 +19,6 @@ import com.google.gwt.core.ext.GeneratorContext; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.linker.GeneratedResource; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JPackage; @@ -212,7 +211,7 @@ // Determine the set of serializable types SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( - logger, typeOracle); + logger, context.getPropertyOracle(), typeOracle); try { addRequiredRoots(logger, typeOracle, stob); @@ -229,8 +228,9 @@ serviceIntf.getQualifiedSourceName() + ".rpc.log"); stob.setLogOutputStream(pathInfo); SerializableTypeOracle sto = stob.build(logger); - GeneratedResource rpcLog = context.commitResource(logger, pathInfo); - rpcLog.setPrivate(true); + if (pathInfo != null) { + context.commitResource(logger, pathInfo).setPrivate(true); + } TypeSerializerCreator tsc = new TypeSerializerCreator(logger, sto, context, sto.getTypeSerializerQualifiedName(serviceIntf)); @@ -346,7 +346,7 @@ String requestIdName = nameFactory.createName("requestId"); w.println("int " + requestIdName + " = getNextRequestId();"); - String statsMethodExpr = getProxySimpleName() + "." + syncMethod.getName(); + String statsMethodExpr = getProxySimpleName() + "." + syncMethod.getName(); String tossName = nameFactory.createName("toss"); w.println("boolean " + tossName + " = isStatsAvailable() && stats(" + "timeStat(\"" + statsMethodExpr + "\", getRequestId(), \"begin\"));"); @@ -411,8 +411,8 @@ w.println("String " + payloadName + " = " + streamWriterName + ".toString();"); - w.println(tossName + " = isStatsAvailable() && stats(" - + "timeStat(\"" + statsMethodExpr + "\", getRequestId(), \"requestSerialized\"));"); + w.println(tossName + " = isStatsAvailable() && stats(" + "timeStat(\"" + + statsMethodExpr + "\", getRequestId(), \"requestSerialized\"));"); /* * Depending on the return type for the async method, return a
diff --git a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java index f1a9e0b..3bd7a0f 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java +++ b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.user.rebind.rpc; +import com.google.gwt.core.ext.PropertyOracle; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.TreeLogger.Type; @@ -452,13 +453,15 @@ * Returns <code>true</code> if the field qualifies for serialization * without considering its type. */ - static boolean shouldConsiderForSerialization(TreeLogger logger, JField field) { + static boolean shouldConsiderForSerialization(TreeLogger logger, + boolean suppressNonStaticFinalFieldWarnings, JField field) { if (field.isStatic() || field.isTransient()) { return false; } if (field.isFinal()) { - logger.branch(TreeLogger.DEBUG, "Field '" + field.toString() + logger.branch(suppressNonStaticFinalFieldWarnings ? TreeLogger.DEBUG + : TreeLogger.WARN, "Field '" + field.toString() + "' will not be serialized because it is final", null); return false; } @@ -577,6 +580,12 @@ private final Map<JClassType, TreeLogger> rootTypes = new LinkedHashMap<JClassType, TreeLogger>(); + /** + * If <code>true</code> we will not warn if a serializable type contains a + * non-static final field. We warn because these fields are not serialized. + */ + private final boolean suppressNonStaticFinalFieldWarnings; + private final TypeConstrainer typeConstrainer; private TypeFilter typeFilter = DEFAULT_TYPE_FILTER; @@ -602,12 +611,14 @@ * Constructs a builder. * * @param logger + * @param propertyOracle * @param typeOracle * * @throws UnableToCompleteException if we fail to find one of our special * types */ - public SerializableTypeOracleBuilder(TreeLogger logger, TypeOracle typeOracle) + public SerializableTypeOracleBuilder(TreeLogger logger, + PropertyOracle propertyOracle, TypeOracle typeOracle) throws UnableToCompleteException { this.typeOracle = typeOracle; typeConstrainer = new TypeConstrainer(typeOracle); @@ -619,6 +630,9 @@ logger.log(TreeLogger.ERROR, null, e); throw new UnableToCompleteException(); } + + suppressNonStaticFinalFieldWarnings = Shared.shouldSuppressNonStaticFinalFieldWarnings( + logger, propertyOracle); } public void addRootType(TreeLogger logger, JType type) { @@ -907,34 +921,31 @@ "Analyzing component type:", null); Set<JClassType> instantiableTypes = new HashSet<JClassType>(); - boolean succeeded = checkTypeInstantiable(branch, array.getComponentType(), - isSpeculative, TypePaths.createArrayComponentPath(array, path), - instantiableTypes); - if (succeeded && leafClass != null) { - TreeLogger covariantArrayLogger = logger.branch(TreeLogger.DEBUG, - "Covariant array types"); + boolean succeeded = checkTypeInstantiable(branch, leafType, isSpeculative, + TypePaths.createArrayComponentPath(array, path), instantiableTypes); + if (succeeded) { + if (leafClass == null) { + assert leafType.isPrimitive() != null; + markArrayTypesInstantiable(leafType, array.getRank(), path); + } else { + TreeLogger covariantArrayLogger = logger.branch(TreeLogger.DEBUG, + "Covariant array types"); - /* - * Compute covariant arrays for arrays of reference types. - */ - for (JClassType instantiableType : TypeHierarchyUtils.getAllTypesBetweenRootTypeAndLeaves( - leafClass, instantiableTypes)) { - if (!isAccessibleToSerializer(instantiableType)) { - // Skip types that are not accessible from a serializer - continue; - } + /* + * Compute covariant arrays for arrays of reference types. + */ + for (JClassType instantiableType : TypeHierarchyUtils.getAllTypesBetweenRootTypeAndLeaves( + leafClass, instantiableTypes)) { + if (!isAccessibleToSerializer(instantiableType)) { + // Skip types that are not accessible from a serializer + continue; + } - covariantArrayLogger.branch( - TreeLogger.DEBUG, - getArrayType(typeOracle, array.getRank(), instantiableType).getParameterizedQualifiedSourceName()); + covariantArrayLogger.branch( + TreeLogger.DEBUG, + getArrayType(typeOracle, array.getRank(), instantiableType).getParameterizedQualifiedSourceName()); - for (int rank = 1; rank <= array.getRank(); ++rank) { - JArrayType covariantArray = getArrayType(typeOracle, rank, - instantiableType); - - TypeInfoComputed covariantArrayTic = getTypeInfoComputed( - covariantArray, path); - covariantArrayTic.setInstantiable(true); + markArrayTypesInstantiable(instantiableType, array.getRank(), path); } } } @@ -973,7 +984,8 @@ + "' that qualify for serialization", null); for (JField field : fields) { - if (!shouldConsiderForSerialization(localLogger, field)) { + if (!shouldConsiderForSerialization(localLogger, + suppressNonStaticFinalFieldWarnings, field)) { continue; } @@ -1101,10 +1113,14 @@ originalType); TypeInfoComputed tic = getTypeInfoComputed(candidate, subtypePath); if (tic.isDone()) { - anySubtypes |= tic.isInstantiable(); + if (tic.isInstantiable()) { + anySubtypes = true; + instSubtypes.add(candidate); + } continue; } else if (tic.isPendingInstantiable()) { anySubtypes = true; + instSubtypes.add(candidate); continue; } tic.setPendingInstantiable(); @@ -1182,8 +1198,8 @@ } } - TypePath path = TypePaths.createTypeArgumentPath(parent, baseType, paramIndex, - typeArg); + TypePath path = TypePaths.createTypeArgumentPath(parent, baseType, + paramIndex, typeArg); int exposure = getTypeParameterExposure(baseType, paramIndex); switch (exposure) { case TypeParameterExposureComputer.EXPOSURE_DIRECT: { @@ -1359,6 +1375,21 @@ } } + /** + * Mark arrays of <code>leafType</code> as instantiable, for arrays of + * dimension up to <code>maxRank</code>. + */ + private void markArrayTypesInstantiable(JType leafType, int maxRank, + TypePath path) { + for (int rank = 1; rank <= maxRank; ++rank) { + JArrayType covariantArray = getArrayType(typeOracle, rank, leafType); + + TypeInfoComputed covariantArrayTic = getTypeInfoComputed(covariantArray, + path); + covariantArrayTic.setInstantiable(true); + } + } + private boolean maybeInstantiable(TreeLogger logger, JClassType type) { boolean success = canBeInstantiated(logger, type, TreeLogger.DEBUG) && shouldConsiderFieldsForSerialization(logger, type, true);
diff --git a/user/src/com/google/gwt/user/rebind/rpc/Shared.java b/user/src/com/google/gwt/user/rebind/rpc/Shared.java index 0154fbb..e5d7992 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/Shared.java +++ b/user/src/com/google/gwt/user/rebind/rpc/Shared.java
@@ -31,8 +31,13 @@ * Property used to control whether or not the RPC system will enforce the * versioning scheme or not. */ - static final String RPC_PROP_ENFORCE_TYPE_VERSIONING = - "gwt.enforceRPCTypeVersioning"; + static final String RPC_PROP_ENFORCE_TYPE_VERSIONING = "gwt.enforceRPCTypeVersioning"; + + /** + * Property used to control whether or not the RPC system will emit warnings + * when a type has final fields. + */ + private static final String RPC_PROP_SUPPRESS_NON_STATIC_FINAL_FIELD_WARNINGS = "gwt.suppressNonStaticFinalFieldWarnings"; /** * Capitalizes a name. @@ -58,19 +63,18 @@ */ static boolean shouldEnforceTypeVersioning(TreeLogger logger, PropertyOracle propertyOracle) { - try { - String propVal = - propertyOracle.getPropertyValue(logger, - RPC_PROP_ENFORCE_TYPE_VERSIONING); - if (propVal.equals("false")) { - return false; - } - } catch (BadPropertyValueException e) { - // Purposely ignored, because we want to enforce RPC versioning if - // the property is not defined. - } - // Assume type versioning unless the user explicitly turns it off. - return true; + return getBooleanProperty(logger, propertyOracle, + RPC_PROP_ENFORCE_TYPE_VERSIONING, true); + } + + /** + * Returns <code>true</code> if warnings should not be emitted for final + * fields in serializable types. + */ + static boolean shouldSuppressNonStaticFinalFieldWarnings(TreeLogger logger, + PropertyOracle propertyOracle) { + return getBooleanProperty(logger, propertyOracle, + RPC_PROP_SUPPRESS_NON_STATIC_FINAL_FIELD_WARNINGS, false); } /** @@ -123,7 +127,7 @@ // className = className.replace('.', '_'); - return new String[]{packageName, className}; + return new String[] {packageName, className}; } /** @@ -137,8 +141,21 @@ */ static boolean typeNeedsCast(JType type) { return type.isPrimitive() == null - && !type.getQualifiedSourceName().equals("java.lang.String") - && !type.getQualifiedSourceName().equals("java.lang.Object"); + && !type.getQualifiedSourceName().equals("java.lang.String") + && !type.getQualifiedSourceName().equals("java.lang.Object"); + } + + private static boolean getBooleanProperty(TreeLogger logger, + PropertyOracle propertyOracle, String propertyName, boolean defaultValue) { + try { + String propVal = propertyOracle.getPropertyValue(logger, propertyName); + if (propVal != null && propVal.length() > 0) { + return Boolean.valueOf(propVal); + } + } catch (BadPropertyValueException e) { + // Just return the default value. + } + return defaultValue; } /**
diff --git a/user/src/com/google/gwt/user/rebind/rpc/TypeParameterExposureComputer.java b/user/src/com/google/gwt/user/rebind/rpc/TypeParameterExposureComputer.java index e3a2ba4..aab0345 100644 --- a/user/src/com/google/gwt/user/rebind/rpc/TypeParameterExposureComputer.java +++ b/user/src/com/google/gwt/user/rebind/rpc/TypeParameterExposureComputer.java
@@ -87,7 +87,7 @@ JField[] fields = type.getFields(); for (JField field : fields) { if (!SerializableTypeOracleBuilder.shouldConsiderForSerialization( - TreeLogger.NULL, field)) { + TreeLogger.NULL, true, field)) { continue; } @@ -271,7 +271,7 @@ JField[] fields = type.getFields(); for (JField field : fields) { if (!SerializableTypeOracleBuilder.shouldConsiderForSerialization( - TreeLogger.NULL, field)) { + TreeLogger.NULL, true, field)) { continue; }
diff --git a/user/src/com/google/gwt/user/server/rpc/RPCServletUtils.java b/user/src/com/google/gwt/user/server/rpc/RPCServletUtils.java index c020de9..f8e8400 100644 --- a/user/src/com/google/gwt/user/server/rpc/RPCServletUtils.java +++ b/user/src/com/google/gwt/user/server/rpc/RPCServletUtils.java
@@ -103,43 +103,37 @@ */ public static String readContentAsUtf8(HttpServletRequest request) throws IOException, ServletException { + return readContentAsUtf8(request, true); + } + + /** + * Returns the content of an {@link HttpServletRequest} by decoding it using + * the UTF-8 charset. + * + * @param request the servlet request whose content we want to read + * @param checkHeaders Specify 'true' to check the Content-Type header to see + * that it matches the expected value 'text/x-gwt-rpc' and the + * content encoding is UTF-8. Disabling this check may allow some + * types of cross type security attacks. + * @return the content of an {@link HttpServletRequest} by decoding it using + * the UTF-8 charset + * @throws IOException if the requests input stream cannot be accessed, read + * from or closed + * @throws ServletException if the content length of the request is not + * specified of if the request's content type is not + * 'text/x-gwt-rpc' and 'charset=utf-8' + */ + public static String readContentAsUtf8(HttpServletRequest request, + boolean checkHeaders) throws IOException, ServletException { int contentLength = request.getContentLength(); if (contentLength == -1) { // Content length must be known. throw new ServletException("Content-Length must be specified"); } - String contentType = request.getContentType(); - boolean contentTypeIsOkay = false; - // Content-Type must be specified. - if (contentType != null) { - contentType = contentType.toLowerCase(); - /* - * The Content-Type must be text/x-gwt-rpc. - * - * NOTE:We use startsWith because some servlet engines, i.e. Tomcat, do - * not remove the charset component but others do. - */ - if (contentType.startsWith(EXPECTED_CONTENT_TYPE)) { - String characterEncoding = request.getCharacterEncoding(); - if (characterEncoding != null) { - /* - * TODO: It would seem that we should be able to use equalsIgnoreCase - * here instead of indexOf. Need to be sure that servlet engines - * return a properly parsed character encoding string if we decide to - * make this change. - */ - if (characterEncoding.toLowerCase().indexOf( - CHARSET_UTF8.toLowerCase()) != -1) { - contentTypeIsOkay = true; - } - } - } - } - - if (!contentTypeIsOkay) { - throw new ServletException("Content-Type must be '" - + EXPECTED_CONTENT_TYPE + "' with '" + EXPECTED_CHARSET + "'."); + if (checkHeaders) { + checkContentType(request); + checkCharacterEncoding(request); } InputStream in = request.getInputStream(); @@ -266,6 +260,67 @@ } } + /** + * Performs validation of the character encoding. + * + * @param request the incoming request. + * @throws ServletException if requests encoding is not UTF-8 + */ + private static void checkCharacterEncoding(HttpServletRequest request) + throws ServletException { + boolean encodingOkay = false; + String characterEncoding = request.getCharacterEncoding(); + if (characterEncoding != null) { + /* + * TODO: It would seem that we should be able to use equalsIgnoreCase here + * instead of indexOf. Need to be sure that servlet engines return a + * properly parsed character encoding string if we decide to make this + * change. + */ + if (characterEncoding.toLowerCase().indexOf(CHARSET_UTF8.toLowerCase()) != -1) { + encodingOkay = true; + } + } + + if (!encodingOkay) { + throw new ServletException("Character Encoding is '" + + (characterEncoding == null ? "(null)" : characterEncoding) + + "'. Expected '" + EXPECTED_CHARSET + "'"); + } + } + + /** + * Performs Content-Type validation of the incoming request. + * + * @param request the incoming request. + * @throws ServletException if the request's content type is not + * 'text/x-gwt-rpc' + */ + private static void checkContentType(HttpServletRequest request) + throws ServletException { + String contentType = request.getContentType(); + boolean contentTypeIsOkay = false; + + if (contentType != null) { + contentType = contentType.toLowerCase(); + /* + * The Content-Type must be text/x-gwt-rpc. + * + * NOTE:We use startsWith because some servlet engines, i.e. Tomcat, do + * not remove the charset component but others do. + */ + if (contentType.startsWith(EXPECTED_CONTENT_TYPE)) { + contentTypeIsOkay = true; + } + } + + if (!contentTypeIsOkay) { + throw new ServletException("Content-Type was '" + + (contentType == null ? "(null)" : contentType) + "'. Expected '" + + EXPECTED_CONTENT_TYPE + "'."); + } + } + private RPCServletUtils() { // Not instantiable }
diff --git a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java index 652c757..e5e9747 100644 --- a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java +++ b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
@@ -27,6 +27,7 @@ import java.util.Map; import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -73,7 +74,7 @@ // Read the request fully. // - String requestPayload = RPCServletUtils.readContentAsUtf8(request); + String requestPayload = readContent(request); // Let subclasses see the serialized request. // @@ -228,7 +229,8 @@ try { if (is != null) { try { - serializationPolicy = SerializationPolicyLoader.loadFromStream(is, null); + serializationPolicy = SerializationPolicyLoader.loadFromStream(is, + null); } catch (ParseException e) { getServletContext().log( "ERROR: Failed to parse the policy file '" @@ -319,9 +321,24 @@ } /** + * Override this method in order to control the parsing of the incoming + * request. For example, you may want to bypass the check of the Content-Type + * and character encoding headers in the request, as some proxies re-write the + * request headers. Note that bypassing these checks may expose the servlet to + * some cross-site vulnerabilities. + * + * @param request the incoming request + * @return the content of the incoming request encoded as a string. + */ + protected String readContent(HttpServletRequest request) + throws ServletException, IOException { + return RPCServletUtils.readContentAsUtf8(request, true); + } + + /** * Determines whether the response to a given servlet request should or should * not be GZIP compressed. This method is only called in cases where the - * requestor accepts GZIP encoding. + * requester accepts GZIP encoding. * <p> * This implementation currently returns <code>true</code> if the response * string's estimated byte length is longer than 256 bytes. Subclasses can
diff --git a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc index 511681b..eae6bd1 100644 --- a/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc +++ b/user/src/com/google/gwt/user/tools/AppClassTemplate.javasrc
@@ -20,10 +20,14 @@ public void onModuleLoad() { Image img = new Image("http://code.google.com/webtoolkit/logo-185x175.png"); Button button = new Button("Click me"); - + + // We can add style names + button.addStyleName("pc-template-btn"); + // or we can set an id on a specific element for styling + img.getElement().setId("pc-template-img"); + VerticalPanel vPanel = new VerticalPanel(); - // We can add style names. - vPanel.addStyleName("widePanel"); + vPanel.setWidth("100%"); vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER); vPanel.add(img); vPanel.add(button);
diff --git a/user/src/com/google/gwt/user/tools/AppCss.csssrc b/user/src/com/google/gwt/user/tools/AppCss.csssrc index 9c6a381..3cf302f 100644 --- a/user/src/com/google/gwt/user/tools/AppCss.csssrc +++ b/user/src/com/google/gwt/user/tools/AppCss.csssrc
@@ -1,13 +1,12 @@ /** Add css rules here for your application. */ -button { + + +/** Example rules used by the template application (remove for your app) */ +.pc-template-btn { display: block; font-size: 16pt } -.widePanel { - width: 100% -} - -img { +#pc-template-img { margin-top: 20px; -} \ No newline at end of file +}
diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 7dd5f8c..3c80553 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java
@@ -667,13 +667,14 @@ count++; } } - // all blank delimiters at the end are supposed to disappear if maxMatch ==0 + // all blank delimiters at the end are supposed to disappear if maxMatch == 0 if (maxMatch == 0) { - for (var i = out.length - 1; i >= 0; i--) { - if(out[i] != "") { - out.splice(i + 1,out.length - (i + 1)); - break; - } + var lastNonEmpty = out.length; + while (lastNonEmpty > 0 && out[lastNonEmpty - 1] == "") { + --lastNonEmpty; + } + if (lastNonEmpty < out.length) { + out.splice(lastNonEmpty, out.length - lastNonEmpty); } } var jr = @java.lang.String::__createArray(I)(out.length);
diff --git a/user/super/com/google/gwt/emul/java/util/Arrays.java b/user/super/com/google/gwt/emul/java/util/Arrays.java index a12e24e..ed22899 100644 --- a/user/super/com/google/gwt/emul/java/util/Arrays.java +++ b/user/super/com/google/gwt/emul/java/util/Arrays.java
@@ -31,7 +31,12 @@ private static final class ArrayList<E> extends AbstractList<E> implements RandomAccess, Serializable { - private final E[] array; + + /** + * The only reason this is non-final is so that E[] (and E) will be exposed + * for serialization. + */ + private E[] array; ArrayList(E[] array) { assert (array != null);
diff --git a/user/super/com/google/gwt/emul/java/util/TreeMap.java b/user/super/com/google/gwt/emul/java/util/TreeMap.java index fa3cb12..2edb562 100644 --- a/user/super/com/google/gwt/emul/java/util/TreeMap.java +++ b/user/super/com/google/gwt/emul/java/util/TreeMap.java
@@ -71,13 +71,8 @@ } public void remove() { - if (last == null) { - throw new IllegalStateException("Must call next() before remove()."); - } else { - iter.remove(); - TreeMap.this.remove(last.getKey()); - last = null; - } + iter.remove(); + TreeMap.this.remove(last.getKey()); } private void inOrderAdd(List<Map.Entry<K, V>> list, SubMapType type, @@ -97,12 +92,12 @@ } private boolean inRange(SubMapType type, K key, K fromKey, K toKey) { - if (type == SubMapType.Head || type == SubMapType.Range) { + if (type.toKeyValid()) { if (cmp.compare(key, toKey) >= 0) { return false; } } - if (type == SubMapType.Tail || type == SubMapType.Range) { + if (type.fromKeyValid()) { if (cmp.compare(key, fromKey) < 0) { return false; } @@ -337,6 +332,11 @@ } @Override + public boolean isEmpty() { + return SubMap.this.isEmpty(); + } + + @Override public Iterator<Entry<K, V>> iterator() { return new EntryIterator(type, fromKey, toKey); } @@ -372,8 +372,8 @@ } public K firstKey() { - Node<K, V> node = getNodeAtOrAfter(fromKey); - if (node == null || cmp.compare(node.key, toKey) > 0) { + Node<K, V> node = throwNSE(getFirstSubmapNode()); + if (type.toKeyValid() && cmp.compare(node.key, toKey) > 0) { throw new NoSuchElementException(); } return node.key; @@ -390,20 +390,25 @@ } public SortedMap<K, V> headMap(K toKey) { - if (cmp.compare(toKey, this.toKey) > 0) { + if (type.toKeyValid() && cmp.compare(toKey, this.toKey) > 0) { throw new IllegalArgumentException("subMap: " + toKey + " greater than " + this.toKey); } - if (type == SubMapType.Range || type == SubMapType.Tail) { + if (type.fromKeyValid()) { return TreeMap.this.subMap(fromKey, toKey); } else { return TreeMap.this.headMap(toKey); } } + @Override + public boolean isEmpty() { + return getFirstSubmapNode() == null; + } + public K lastKey() { - Node<K, V> node = getNodeBefore(toKey); - if (node == null || cmp.compare(node.key, fromKey) < 0) { + Node<K, V> node = throwNSE(getLastSubmapNode()); + if (type.fromKeyValid() && cmp.compare(node.key, fromKey) < 0) { throw new NoSuchElementException(); } return node.key; @@ -429,13 +434,11 @@ } public SortedMap<K, V> subMap(K newFromKey, K newToKey) { - if ((type == SubMapType.Range || type == SubMapType.Tail) - && cmp.compare(newFromKey, fromKey) < 0) { + if (type.fromKeyValid() && cmp.compare(newFromKey, fromKey) < 0) { throw new IllegalArgumentException("subMap: " + newFromKey + " less than " + fromKey); } - if ((type == SubMapType.Range || type == SubMapType.Head) - && cmp.compare(newToKey, toKey) > 0) { + if (type.toKeyValid() && cmp.compare(newToKey, toKey) > 0) { throw new IllegalArgumentException("subMap: " + newToKey + " greater than " + toKey); } @@ -443,25 +446,44 @@ } public SortedMap<K, V> tailMap(K fromKey) { - if ((type == SubMapType.Range || type == SubMapType.Tail) - && cmp.compare(fromKey, this.fromKey) < 0) { + if (type.fromKeyValid() && cmp.compare(fromKey, this.fromKey) < 0) { throw new IllegalArgumentException("subMap: " + fromKey + " less than " + this.fromKey); } - if (type == SubMapType.Range || type == SubMapType.Head) { + if (type.toKeyValid()) { return TreeMap.this.subMap(fromKey, toKey); } else { return TreeMap.this.tailMap(fromKey); } } + private Node<K, V> getFirstSubmapNode() { + Node<K, V> node; + if (type.fromKeyValid()) { + node = getNodeAtOrAfter(fromKey); + } else { + node = getFirstNode(); + } + return node; + } + + private Node<K, V> getLastSubmapNode() { + Node<K, V> node; + if (type.toKeyValid()) { + node = getNodeBefore(toKey); + } else { + node = getLastNode(); + } + return node; + } + private boolean inRange(K key) { - if (type == SubMapType.Head || type == SubMapType.Range) { + if (type.toKeyValid()) { if (cmp.compare(key, toKey) >= 0) { return false; } } - if (type == SubMapType.Tail || type == SubMapType.Range) { + if (type.fromKeyValid()) { if (cmp.compare(key, fromKey) < 0) { return false; } @@ -471,7 +493,47 @@ } private enum SubMapType { - All, Head, Range, Tail, + All, + + Head { + @Override + public boolean toKeyValid() { + return true; + } + }, + + Range { + @Override + public boolean fromKeyValid() { + return true; + } + + @Override + public boolean toKeyValid() { + return true; + } + }, + + Tail { + @Override + public boolean fromKeyValid() { + return true; + } + }; + + /** + * @return true if this submap type uses a from-key. + */ + public boolean fromKeyValid() { + return false; + } + + /** + * @return true if this submap type uses a to-key. + */ + public boolean toKeyValid() { + return false; + } } /** @@ -497,6 +559,24 @@ return 1 - child; } + /** + * Throw a NoSuchElementException if the specified node is null. + * + * Used to clean up error checking at use sites. + * + * @param node node to check + * @param <NK> key type + * @param <NV> value type + * @return node, guaranteed to be non-null + * @throws NoSuchElementException if node is null + */ + private static <NK, NV> Node<NK, NV> throwNSE(Node<NK, NV> node) { + if (node == null) { + throw new NoSuchElementException(); + } + return node; + } + // The comparator to use. private Comparator<? super K> cmp; @@ -555,14 +635,7 @@ } public K firstKey() { - if (root == null) { - throw new NoSuchElementException(); - } - Node<K, V> node = root; - while (node.child[LEFT] != null) { - node = node.child[LEFT]; - } - return node.key; + return throwNSE(getFirstNode()).key; } @SuppressWarnings("unchecked") @@ -584,14 +657,7 @@ } public K lastKey() { - if (root == null) { - throw new NoSuchElementException(); - } - Node<K, V> node = root; - while (node.child[RIGHT] != null) { - node = node.child[RIGHT]; - } - return node.key; + return throwNSE(getLastNode()).key; } @Override @@ -633,66 +699,44 @@ * key. * * @param key the key to search for - * @return the next node, or null if there is none. + * @return the next node, or null if there is none */ protected Node<K, V> getNodeAtOrAfter(K key) { - if (root == null) { - return null; - } Node<K, V> foundNode = null; Node<K, V> node = root; - while (true) { + while (node != null) { int c = cmp.compare(key, node.key); if (c == 0) { return node; } else if (c > 0) { node = node.child[RIGHT]; - if (node == null) { - // ran off the tree and we are past this node, so return best one - return foundNode; - } } else { foundNode = node; - Node<K, V> nextNode = node.child[LEFT]; - if (nextNode == null) { - // ran off the tree and we are before this node, so return it - return node; - } - node = nextNode; + node = node.child[LEFT]; } } + return foundNode; } /** * Return the last node which is strictly less than the given key. * * @param key the key to search for - * @return the previous node, or null if there is none. + * @return the previous node, or null if there is none */ protected Node<K, V> getNodeBefore(K key) { - if (root == null) { - return null; - } Node<K, V> foundNode = null; Node<K, V> node = root; - while (true) { + while (node != null) { int c = cmp.compare(key, node.key); if (c <= 0) { node = node.child[LEFT]; - if (node == null) { - // ran off the tree and we are past this node, so return best one - return foundNode; - } } else { foundNode = node; - Node<K, V> nextNode = node.child[RIGHT]; - if (nextNode == null) { - // ran off the tree and we are before this node, so return it - return node; - } - node = nextNode; + node = node.child[RIGHT]; } } + return foundNode; } /** @@ -712,7 +756,7 @@ } /** - * Internal helper function for public (@see assertCorrectness()). + * Internal helper function for public {@link #assertCorrectness()}. * * @param tree the subtree to validate. * @param isRed true if the parent of this node is red. @@ -768,6 +812,47 @@ return null; } + /** + * @return the left-most node of the tree, or null if empty + */ + private Node<K, V> getFirstNode() { + if (root == null) { + return null; + } + Node<K, V> node = root; + while (node.child[LEFT] != null) { + node = node.child[LEFT]; + } + return node; + } + + /** + * @return the right-most node of the tree, or null if empty + */ + private Node<K, V> getLastNode() { + if (root == null) { + return null; + } + Node<K, V> node = root; + while (node.child[RIGHT] != null) { + node = node.child[RIGHT]; + } + return node; + } + + /** + * Insert a node into a subtree, collecting state about the insertion. + * + * If the same key already exists, the value of the node is overwritten + * with the value from the new node instead. + * + * @param tree subtree to insert into + * @param newNode new node to insert + * @param state result of the insertion: + * state.found true if the key already existed in the tree + * state.value the old value if the key existed + * @return the new subtree root + */ private Node<K, V> insert(Node<K, V> tree, Node<K, V> newNode, State<V> state) { if (tree == null) { return newNode; @@ -779,7 +864,7 @@ tree.value = newNode.value; return tree; } - int childNum = (c > 0) ? 0 : 1; + int childNum = (c > 0) ? LEFT : RIGHT; tree.child[childNum] = insert(tree.child[childNum], newNode, state); if (isRed(tree.child[childNum])) { if (isRed(tree.child[otherChild(childNum)])) {
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java index 7eb613b..4c744e7 100644 --- a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
@@ -615,6 +615,23 @@ } fail("should not be reached"); } + + /* + * Issue 2770: labeled breaks in a switch statement with no default case + * should not be pruned. + */ + outer : while (true) { + switch (THREE) { + case 0: + case 1: + case 2: + case 3: + break outer; + case 4: + case 5: + break; + } + } } public void testLocalClasses() {
diff --git a/user/test/com/google/gwt/dev/jjs/test/HostedTest.java b/user/test/com/google/gwt/dev/jjs/test/HostedTest.java index 8ba7541..a28f341 100644 --- a/user/test/com/google/gwt/dev/jjs/test/HostedTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
@@ -54,18 +54,6 @@ } } - private static class TestGenericList extends AbstractList<Object> { - @Override - public Object get(int index) { - return this; - } - - @Override - public int size() { - return 42; - } - } - private static class TestCovariantChild extends TestCovariantSuper { @Override public native String foo(String val) /*-{ @@ -96,6 +84,18 @@ }-*/; } + private static class TestGenericList extends AbstractList<Object> { + @Override + public Object get(int index) { + return this; + } + + @Override + public int size() { + return 42; + } + } + static String sFoo(String s) { return s + "foo"; }
diff --git a/user/test/com/google/gwt/dev/jjs/test/JsniConstructorTest.java b/user/test/com/google/gwt/dev/jjs/test/JsniConstructorTest.java index 29d0f2f..657b2ae 100644 --- a/user/test/com/google/gwt/dev/jjs/test/JsniConstructorTest.java +++ b/user/test/com/google/gwt/dev/jjs/test/JsniConstructorTest.java
@@ -28,6 +28,49 @@ */ public class JsniConstructorTest extends GWTTestCase { + private interface A1 { + void a1(); + } + + private interface A2 extends A1 { + void a2(); + } + + private interface A3 { + void a3(); + } + + private static abstract class C1 implements A2 { + static void s1() { + } + + public abstract void c1(); + } + + private static class C2 extends C1 implements A3 { + static void s2() { + } + + public void a1() { + } + + public void a2() { + } + + public void a3() { + } + + public void c1() { + } + + public void c2() { + } + + public String toString() { + return null; + } + } + @Override public String getModuleName() { return "com.google.gwt.dev.jjs.CompilerSuite"; @@ -45,7 +88,7 @@ } catch (Throwable t) { fail("Expecting a StaticObjectException, got a " + t.getClass().getName()); } - + try { staticArg(true); fail("Should have thrown a runtime exception"); @@ -55,7 +98,35 @@ fail("Expecting a RuntimeException, got a " + t.getClass().getName()); } } - + + public native void testInheritedMethodRef() /*-{ + @com.google.gwt.dev.jjs.test.JsniConstructorTest.C1::s1()(); + @com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::s1()(); + @com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::s2()(); + + var o = @com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::new()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.A1::a1()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.A2::a1()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C1::a1()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::a1()(); + + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.A2::a2()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C1::a2()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::a2()(); + + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.A3::a3()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::a3()(); + + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C1::c1()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::c1()(); + + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::c2()(); + + o.@java.lang.Object::toString()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C1::toString()(); + o.@com.google.gwt.dev.jjs.test.JsniConstructorTest.C2::toString()(); + }-*/; + public void testJsniConstructors() { StaticObject o = staticArg(1); assertEquals(1, o.foo()); @@ -83,43 +154,45 @@ } private native InstanceObject instanceArg(StaticObject obj, int i) /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject;I)(obj,i); + return @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject;I)(obj,i); }-*/; - private native NestedInstanceObject nestedInstanceArg(InstanceObject obj, int i) /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject.NestedInstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject$InstanceObject;I)(obj,i); + private native NestedInstanceObject nestedInstanceArg(InstanceObject obj, + int i) /*-{ + return @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject.NestedInstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject$InstanceObject;I)(obj,i); }-*/; private native NoArgObject noArg() /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject.NoArgObject::new()(); + return @com.google.gwt.dev.jjs.test.StaticObject.NoArgObject::new()(); }-*/; private native NoInitObject noInit() /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject.NoInitObject::new()(); + return @com.google.gwt.dev.jjs.test.StaticObject.NoInitObject::new()(); }-*/; private native InstanceObject passAndReturnInstance(StaticObject obj, int i) /*-{ - var f = @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject;I); - return f.call(null, obj, i); + var f = @com.google.gwt.dev.jjs.test.StaticObject.InstanceObject::new(Lcom/google/gwt/dev/jjs/test/StaticObject;I); + return f.call(null, obj, i); }-*/; private native StaticObject passAndReturnStatic(int i) /*-{ - var f = @com.google.gwt.dev.jjs.test.StaticObject::new(I); - return f(i); + var f = @com.google.gwt.dev.jjs.test.StaticObject::new(I); + return f(i); }-*/; /** * Calls a constructor that always throws an exception. */ - private native StaticObject staticArg(boolean throwRuntime) throws StaticObjectException /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject::new(Z)(throwRuntime); + private native StaticObject staticArg(boolean throwRuntime) + throws StaticObjectException /*-{ + return @com.google.gwt.dev.jjs.test.StaticObject::new(Z)(throwRuntime); }-*/; - + private native StaticObject staticArg(int i) /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject::new(I)(i); + return @com.google.gwt.dev.jjs.test.StaticObject::new(I)(i); }-*/; private native StaticInnerObject staticInnerArg(int i) /*-{ - return @com.google.gwt.dev.jjs.test.StaticObject.StaticInnerObject::new(I)(i); + return @com.google.gwt.dev.jjs.test.StaticObject.StaticInnerObject::new(I)(i); }-*/; }
diff --git a/user/test/com/google/gwt/dom/client/ElementTest.java b/user/test/com/google/gwt/dom/client/ElementTest.java index 9fb4657..0471fb5 100644 --- a/user/test/com/google/gwt/dom/client/ElementTest.java +++ b/user/test/com/google/gwt/dom/client/ElementTest.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dom.client; +import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; @@ -304,4 +305,27 @@ assertEquals("foo", nodes.getItem(0).getInnerText()); assertEquals("bar", nodes.getItem(1).getInnerText()); } + + /** + * Tests HeadingElement.as() (it has slightly more complex assertion logic + * than most). + */ + public void testHeadingElementAs() { + DivElement placeHolder = Document.get().createDivElement(); + + for (int i = 0; i < 6; ++i) { + placeHolder.setInnerHTML("<H" + (i + 1) + "/>"); + assertNotNull(HeadingElement.as(placeHolder.getFirstChildElement())); + } + + if (!GWT.isScript()) { + Element notHeading = Document.get().createDivElement(); + try { + HeadingElement.as(notHeading); + fail("Expected assertion failure"); + } catch (AssertionError e) { + // this *should* happen. + } + } + } }
diff --git a/user/test/com/google/gwt/emultest/java/lang/StringTest.java b/user/test/com/google/gwt/emultest/java/lang/StringTest.java index 0041edd..20c1a77 100644 --- a/user/test/com/google/gwt/emultest/java/lang/StringTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/StringTest.java
@@ -393,24 +393,25 @@ public void testSplit() { compareList("fullSplit", new String[] {"abc", "", "", "de", "f"}, - "abcxxxdexfxx".split("x")); + hideFromCompiler("abcxxxdexfxx").split("x")); compareList("emptyRegexSplit", new String[] { "", "a", "b", "c", "x", "x", "d", "e", "x", "f", "x"}, - "abcxxdexfx".split("")); - compareList("2:", "boo:and:foo".split(":", 2), new String[] { - "boo", "and:foo"}); - compareList("5:", "boo:and:foo".split(":", 5), new String[] { - "boo", "and", "foo"}); - compareList("-2:", "boo:and:foo".split(":", -2), new String[] { - "boo", "and", "foo"}); - compareList("5o", "boo:and:foo".split("o", 5), new String[] { - "b", "", ":and:f", "", ""}); - compareList("-2o", "boo:and:foo".split("o", -2), new String[] { - "b", "", ":and:f", "", ""}); - compareList("0o", "boo:and:foo".split("o", 0), new String[] { - "b", "", ":and:f"}); - compareList("0:", "boo:and:foo".split(":", 0), new String[] { - "boo", "and", "foo"}); + hideFromCompiler("abcxxdexfx").split("")); + String booAndFoo = hideFromCompiler("boo:and:foo"); + compareList("2:", new String[] {"boo", "and:foo"}, booAndFoo.split(":", 2)); + compareList("5:", new String[] {"boo", "and", "foo"}, booAndFoo.split(":", + 5)); + compareList("-2:", new String[] {"boo", "and", "foo"}, booAndFoo.split(":", + -2)); + compareList("5o", new String[] {"b", "", ":and:f", "", ""}, + booAndFoo.split("o", 5)); + compareList("-2o", new String[] {"b", "", ":and:f", "", ""}, + booAndFoo.split("o", -2)); + compareList("0o", new String[] {"b", "", ":and:f"}, booAndFoo.split("o", 0)); + compareList("0:", new String[] {"boo", "and", "foo"}, booAndFoo.split(":", + 0)); + // issue 2742 + compareList("issue2742", new String[] {}, hideFromCompiler("/").split("/", 0)); } public void testStartsWith() {
diff --git a/user/test/com/google/gwt/emultest/java/util/TreeMapStringStringTest.java b/user/test/com/google/gwt/emultest/java/util/TreeMapStringStringTest.java index 55a49fc..8f7f714 100644 --- a/user/test/com/google/gwt/emultest/java/util/TreeMapStringStringTest.java +++ b/user/test/com/google/gwt/emultest/java/util/TreeMapStringStringTest.java
@@ -15,11 +15,119 @@ */ package com.google.gwt.emultest.java.util; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; + /** * Tests <code>TreeMap</code> with Strings and the natural comparator. */ public class TreeMapStringStringTest extends TreeMapTest<String, String> { + public void testHeadMapEqualsFirst() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap = sortedMap.headMap("aa"); + assertEquals("length", 0, subMap.size()); + Set<String> kset = subMap.keySet(); + Iterator<String> it = kset.iterator(); + assertFalse("iterator[0]", it.hasNext()); + } + + public void testHeadMapEqualsSecond() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap = sortedMap.headMap("bb"); + assertEquals("length", 1, subMap.size()); + Set<String> kset = subMap.keySet(); + Iterator<String> it = kset.iterator(); + assertTrue("iterator[0]", it.hasNext()); + assertEquals("iterator[0]", "aa", it.next()); + assertFalse("iterator[1]", it.hasNext()); + assertEquals("firstKey", "aa", subMap.firstKey()); + assertEquals("lastKey", "aa", subMap.lastKey()); + } + + /** + * Perform some tests on submap that are hard to do without specific knowledge + * of the keys used. + */ + public void testHeadMapSimple() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap = sortedMap.headMap("bz"); + assertEquals("length", 2, subMap.size()); + Set<String> kset = subMap.keySet(); + Iterator<String> it = kset.iterator(); + assertTrue("iterator[0]", it.hasNext()); + assertEquals("iterator[0]", "aa", it.next()); + assertTrue("iterator[1]", it.hasNext()); + assertEquals("iterator[1]", "bb", it.next()); + assertFalse("iterator[2]", it.hasNext()); + // issue 2638 + assertEquals("firstKey", "aa", subMap.firstKey()); + assertEquals("lastKey", "bb", subMap.lastKey()); + } + + /** + * Tests that compositing submap operations function as expected. + */ + public void testSubMapComposite() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap1 = sortedMap.headMap("cz").tailMap("bb"); + SortedMap<String, String> subMap2 = sortedMap.tailMap("bb").headMap("cz"); + SortedMap<String, String> subMap3 = sortedMap.subMap("bb", "cz"); + assertEquals("headMap(tailMap) should equal tailMap(headMap)", subMap1, + subMap2); + assertEquals("headMap(tailMap) should equal subMap", subMap1, subMap3); + assertEquals("headMap(tailMap) size", 2, subMap1.size()); + } + + public void testTailMapPastEnd() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap = sortedMap.tailMap("dz"); + assertEquals("length", 0, subMap.size()); + Set<String> kset = subMap.keySet(); + Iterator<String> it = kset.iterator(); + assertFalse("iterator[0]", it.hasNext()); + try { + subMap.firstKey(); + fail("firstKey should have thrown NoSuchElementException"); + } catch (NoSuchElementException expected) { + } + try { + subMap.lastKey(); + fail("lastKey should have thrown NoSuchElementException"); + } catch (NoSuchElementException expected) { + } + } + + public void testTailMapSimple() { + SortedMap<String, String> sortedMap = createKnownKeysMap(); + SortedMap<String, String> subMap = sortedMap.tailMap("bb"); + assertEquals("length", 3, subMap.size()); + Set<String> kset = subMap.keySet(); + Iterator<String> it = kset.iterator(); + assertTrue("iterator[0]", it.hasNext()); + assertEquals("iterator[0]", "bb", it.next()); + assertTrue("iterator[1]", it.hasNext()); + assertEquals("iterator[1]", "cc", it.next()); + assertTrue("iterator[2]", it.hasNext()); + assertEquals("iterator[2]", "dd", it.next()); + assertFalse("iterator[3]", it.hasNext()); + // issue 2638 + assertEquals("firstKey", "bb", subMap.firstKey()); + assertEquals("lastKey", "dd", subMap.lastKey()); + } + + @Override + protected Object getConflictingKey() { + return new Integer(1); + } + + @Override + protected Object getConflictingValue() { + return new Long(42); + } + @Override String getGreaterThanMaximumKey() { return "z"; @@ -30,12 +138,6 @@ return convertToStringArray(getSampleKeys()); } - private String[] convertToStringArray(Object[] objArray) { - String[] strArray = new String[objArray.length]; - System.arraycopy(objArray, 0, strArray, 0, objArray.length); - return strArray; - } - @Override String[] getKeys2() { return convertToStringArray(getOtherKeys()); @@ -56,13 +158,18 @@ return convertToStringArray(getOtherValues()); } - @Override - protected Object getConflictingKey() { - return new Integer(1); + private String[] convertToStringArray(Object[] objArray) { + String[] strArray = new String[objArray.length]; + System.arraycopy(objArray, 0, strArray, 0, objArray.length); + return strArray; } - @Override - protected Object getConflictingValue() { - return new Long(42); + private SortedMap<String, String> createKnownKeysMap() { + SortedMap<String, String> sortedMap = createSortedMap(); + sortedMap.put("dd", "dval"); + sortedMap.put("aa", "aval"); + sortedMap.put("cc", "cval"); + sortedMap.put("bb", "bval"); + return sortedMap; } }
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java index 79e1b93..24d44ec 100644 --- a/user/test/com/google/gwt/user/RPCSuite.java +++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -26,6 +26,7 @@ import com.google.gwt.user.client.rpc.ValueTypesTest; import com.google.gwt.user.rebind.rpc.SerializableTypeOracleBuilderTest; import com.google.gwt.user.rebind.rpc.TypeHierarchyUtilsTest; +import com.google.gwt.user.server.rpc.RPCServletUtilsTest; import com.google.gwt.user.server.rpc.RPCTest; import com.google.gwt.user.server.rpc.SerializationPolicyLoaderTest; import com.google.gwt.user.server.rpc.impl.LegacySerializationPolicyTest; @@ -66,7 +67,7 @@ suite.addTestSuite(LegacySerializationPolicyTest.class); suite.addTestSuite(StandardSerializationPolicyTest.class); suite.addTestSuite(SerializationPolicyLoaderTest.class); - + suite.addTestSuite(RPCServletUtilsTest.class); return suite; } }
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java index b35e439..78eac3f 100644 --- a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java +++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
@@ -17,6 +17,12 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector; import java.sql.Time; import java.sql.Timestamp; @@ -29,7 +35,7 @@ import java.util.Vector; /** - * TODO: document me. + * Tests collections across RPC. */ public class CollectionsTest extends GWTTestCase { /** @@ -40,19 +46,22 @@ private CollectionsTestServiceAsync collectionsTestService; - public void _testDateArray() { + /** + * TODO: Why is this disabled??? + */ + public void disabledTestDateArray() { delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); final Date[] expected = TestSetFactory.createDateArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Date[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Date[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Date[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -68,14 +77,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final int[] expected = TestSetFactory.createVeryLargeArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<int[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(int[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (int[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -89,36 +98,38 @@ delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - service.echo(TestSetFactory.createArrayList(), new AsyncCallback() { - public void onFailure(Throwable caught) { - TestSetValidator.rethrowException(caught); - } + service.echo(TestSetFactory.createArrayList(), + new AsyncCallback<ArrayList<MarkerTypeArrayList>>() { + public void onFailure(Throwable caught) { + TestSetValidator.rethrowException(caught); + } - public void onSuccess(Object result) { - assertNotNull(result); - assertTrue(TestSetValidator.isValid((ArrayList) result)); - finishTest(); - } - }); + public void onSuccess(ArrayList<MarkerTypeArrayList> result) { + assertNotNull(result); + assertTrue(TestSetValidator.isValid(result)); + finishTest(); + } + }); } public void testArraysAsList() { delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final List expected = TestSetFactory.createArraysAsList(); + final List<MarkerTypeArraysAsList> expected = TestSetFactory.createArraysAsList(); - service.echoArraysAsList(expected, new AsyncCallback() { - public void onFailure(Throwable caught) { - TestSetValidator.rethrowException(caught); - } + service.echoArraysAsList(expected, + new AsyncCallback<List<MarkerTypeArraysAsList>>() { + public void onFailure(Throwable caught) { + TestSetValidator.rethrowException(caught); + } - public void onSuccess(Object result) { - assertNotNull(result); - assertEquals(expected, result); - finishTest(); - } - }); + public void onSuccess(List<MarkerTypeArraysAsList> result) { + assertNotNull(result); + assertEquals(expected, result); + finishTest(); + } + }); } public void testBooleanArray() { @@ -126,14 +137,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Boolean[] expected = TestSetFactory.createBooleanArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Boolean[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Boolean[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Boolean[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -144,14 +155,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Byte[] expected = TestSetFactory.createByteArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Byte[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Byte[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Byte[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -162,14 +173,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Character[] expected = TestSetFactory.createCharArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Character[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Character[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Character[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -180,14 +191,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Double[] expected = TestSetFactory.createDoubleArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Double[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Double[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Double[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -198,14 +209,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Float[] expected = TestSetFactory.createFloatArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Float[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Float[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Float[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -215,33 +226,34 @@ delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final HashMap expected = TestSetFactory.createHashMap(); - service.echo(expected, new AsyncCallback() { - public void onFailure(Throwable caught) { - TestSetValidator.rethrowException(caught); - } + final HashMap<String, MarkerTypeHashMap> expected = TestSetFactory.createHashMap(); + service.echo(expected, + new AsyncCallback<HashMap<String, MarkerTypeHashMap>>() { + public void onFailure(Throwable caught) { + TestSetValidator.rethrowException(caught); + } - public void onSuccess(Object result) { - assertNotNull(result); - assertTrue(TestSetValidator.isValid(expected, (HashMap) result)); - finishTest(); - } - }); + public void onSuccess(HashMap<String, MarkerTypeHashMap> result) { + assertNotNull(result); + assertTrue(TestSetValidator.isValid(expected, result)); + finishTest(); + } + }); } public void testHashSet() { delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final HashSet expected = TestSetFactory.createHashSet(); - service.echo(expected, new AsyncCallback() { + final HashSet<MarkerTypeHashSet> expected = TestSetFactory.createHashSet(); + service.echo(expected, new AsyncCallback<HashSet<MarkerTypeHashSet>>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(HashSet<MarkerTypeHashSet> result) { assertNotNull(result); - assertTrue(TestSetValidator.isValid(expected, (HashSet) result)); + assertTrue(TestSetValidator.isValid(expected, result)); finishTest(); } }); @@ -252,14 +264,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Integer[] expected = TestSetFactory.createIntegerArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Integer[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Integer[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Integer[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -269,20 +281,20 @@ delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final LinkedHashMap<String, IsSerializable> expected = TestSetFactory.createLinkedHashMap(); + final LinkedHashMap<String, MarkerTypeLinkedHashMap> expected = TestSetFactory.createLinkedHashMap(); service.echo(expected, - new AsyncCallback<LinkedHashMap<String, IsSerializable>>() { + new AsyncCallback<LinkedHashMap<String, MarkerTypeLinkedHashMap>>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(LinkedHashMap<String, IsSerializable> result) { + public void onSuccess( + LinkedHashMap<String, MarkerTypeLinkedHashMap> result) { assertNotNull(result); expected.get("SerializableSet"); result.get("SerializableSet"); - assertTrue(TestSetValidator.isValid(expected, - (LinkedHashMap) result)); + assertTrue(TestSetValidator.isValid(expected, result)); finishTest(); } }); @@ -292,15 +304,16 @@ delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final LinkedHashMap<String, IsSerializable> expected = TestSetFactory.createLRULinkedHashMap(); + final LinkedHashMap<String, MarkerTypeLinkedHashMap> expected = TestSetFactory.createLRULinkedHashMap(); service.echo(expected, - new AsyncCallback<LinkedHashMap<String, IsSerializable>>() { + new AsyncCallback<LinkedHashMap<String, MarkerTypeLinkedHashMap>>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(LinkedHashMap actual) { + public void onSuccess( + LinkedHashMap<String, MarkerTypeLinkedHashMap> actual) { assertNotNull(actual); expected.get("SerializableSet"); actual.get("SerializableSet"); @@ -315,14 +328,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Long[] expected = TestSetFactory.createLongArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Long[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Long[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Long[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -333,13 +346,13 @@ final boolean[] expected = TestSetFactory.createPrimitiveBooleanArray(); CollectionsTestServiceAsync service = getServiceAsync(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<boolean[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { - assertTrue(TestSetValidator.equals(expected, (boolean[]) result)); + public void onSuccess(boolean[] result) { + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -350,13 +363,13 @@ final byte[] expected = TestSetFactory.createPrimitiveByteArray(); CollectionsTestServiceAsync service = getServiceAsync(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<byte[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { - assertTrue(TestSetValidator.equals(expected, (byte[]) result)); + public void onSuccess(byte[] result) { + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -367,14 +380,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final char[] expected = TestSetFactory.createPrimitiveCharArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<char[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(char[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (char[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -385,14 +398,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final double[] expected = TestSetFactory.createPrimitiveDoubleArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<double[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(double[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (double[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -403,14 +416,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final float[] expected = TestSetFactory.createPrimitiveFloatArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<float[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(float[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (float[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -421,14 +434,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final int[] expected = TestSetFactory.createPrimitiveIntegerArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<int[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(int[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (int[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -439,14 +452,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final long[] expected = TestSetFactory.createPrimitiveLongArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<long[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(long[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (long[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -457,14 +470,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final short[] expected = TestSetFactory.createPrimitiveShortArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<short[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(short[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (short[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -475,14 +488,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final Short[] expected = TestSetFactory.createShortArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<Short[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Short[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (Short[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -547,14 +560,14 @@ CollectionsTestServiceAsync service = getServiceAsync(); final String[] expected = TestSetFactory.createStringArray(); - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<String[]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(String[] result) { assertNotNull(result); - assertTrue(TestSetValidator.equals(expected, (String[]) result)); + assertTrue(TestSetValidator.equals(expected, result)); finishTest(); } }); @@ -566,12 +579,12 @@ CollectionsTestServiceAsync service = getServiceAsync(); final String[][] expected = new String[][] { new String[] {"hello"}, new String[] {"bye"}}; - service.echo(expected, new AsyncCallback() { + service.echo(expected, new AsyncCallback<String[][]>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(String[][] result) { assertNotNull(result); finishTest(); } @@ -582,15 +595,15 @@ delayTestFinish(TEST_DELAY); CollectionsTestServiceAsync service = getServiceAsync(); - final Vector expected = TestSetFactory.createVector(); - service.echo(expected, new AsyncCallback() { + final Vector<MarkerTypeVector> expected = TestSetFactory.createVector(); + service.echo(expected, new AsyncCallback<Vector<MarkerTypeVector>>() { public void onFailure(Throwable caught) { TestSetValidator.rethrowException(caught); } - public void onSuccess(Object result) { + public void onSuccess(Vector<MarkerTypeVector> result) { assertNotNull(result); - assertTrue(TestSetValidator.isValid(expected, (Vector) result)); + assertTrue(TestSetValidator.isValid(expected, result)); finishTest(); } });
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java index 84c6330..38590f9 100644 --- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java +++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
@@ -15,6 +15,14 @@ */ package com.google.gwt.user.client.rpc; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector; + import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; @@ -22,6 +30,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; @@ -33,7 +42,7 @@ /** * TODO: document me. */ - public static class CollectionsTestServiceException extends Exception { + final class CollectionsTestServiceException extends Exception { public CollectionsTestServiceException() { } @@ -41,8 +50,7 @@ super(msg); } } - - ArrayList<IsSerializable> echo(ArrayList<IsSerializable> value) + ArrayList<MarkerTypeArrayList> echo(ArrayList<MarkerTypeArrayList> value) throws CollectionsTestServiceException; boolean[] echo(boolean[] value) throws CollectionsTestServiceException; @@ -59,9 +67,6 @@ Date[] echo(Date[] date) throws CollectionsTestServiceException; - java.sql.Date[] echo(java.sql.Date[] value) - throws CollectionsTestServiceException; - double[] echo(double[] value) throws CollectionsTestServiceException; Double[] echo(Double[] value) throws CollectionsTestServiceException; @@ -70,20 +75,28 @@ Float[] echo(Float[] value) throws CollectionsTestServiceException; - HashMap<String, IsSerializable> echo(HashMap<String, IsSerializable> value) + HashMap<String, MarkerTypeHashMap> echo( + HashMap<String, MarkerTypeHashMap> value) throws CollectionsTestServiceException; - LinkedHashMap<String, IsSerializable> echo( - LinkedHashMap<String, IsSerializable> value) - throws CollectionsTestServiceException; - - HashSet<IsSerializable> echo(HashSet<IsSerializable> value) + HashSet<MarkerTypeHashSet> echo(HashSet<MarkerTypeHashSet> value) throws CollectionsTestServiceException; int[] echo(int[] value) throws CollectionsTestServiceException; Integer[] echo(Integer[] value) throws CollectionsTestServiceException; + java.sql.Date[] echo(java.sql.Date[] value) + throws CollectionsTestServiceException; + + LinkedHashMap<String, MarkerTypeLinkedHashMap> echo( + LinkedHashMap<String, MarkerTypeLinkedHashMap> value) + throws CollectionsTestServiceException; + + LinkedHashSet<MarkerTypeLinkedHashSet> echo( + LinkedHashSet<MarkerTypeLinkedHashSet> value) + throws CollectionsTestServiceException; + long[] echo(long[] value) throws CollectionsTestServiceException; Long[] echo(Long[] value) throws CollectionsTestServiceException; @@ -100,9 +113,10 @@ Timestamp[] echo(Timestamp[] value) throws CollectionsTestServiceException; - Vector<IsSerializable> echo(Vector<IsSerializable> value) + Vector<MarkerTypeVector> echo(Vector<MarkerTypeVector> value) throws CollectionsTestServiceException; - List<IsSerializable> echoArraysAsList(List<IsSerializable> value) + List<MarkerTypeArraysAsList> echoArraysAsList( + List<MarkerTypeArraysAsList> value) throws CollectionsTestServiceException; }
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java index 4c9187e..5423060 100644 --- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java +++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2008 Google Inc. * * 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 @@ -15,6 +15,14 @@ */ package com.google.gwt.user.client.rpc; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector; + import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; @@ -22,6 +30,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; @@ -29,8 +38,8 @@ * TODO: document me. */ public interface CollectionsTestServiceAsync { - void echo(ArrayList<IsSerializable> value, - AsyncCallback<ArrayList<IsSerializable>> callback); + void echo(ArrayList<MarkerTypeArrayList> value, + AsyncCallback<ArrayList<MarkerTypeArrayList>> callback); void echo(boolean[] value, AsyncCallback<boolean[]> callback); @@ -46,8 +55,6 @@ void echo(Date[] date, AsyncCallback<Date[]> callback); - void echo(java.sql.Date[] value, AsyncCallback<java.sql.Date[]> callback); - void echo(double[] value, AsyncCallback<double[]> callback); void echo(Double[] value, AsyncCallback<Double[]> callback); @@ -56,19 +63,24 @@ void echo(Float[] value, AsyncCallback<Float[]> callback); - void echo(HashMap<String, IsSerializable> value, - AsyncCallback<HashMap<String, IsSerializable>> callback); + void echo(HashMap<String, MarkerTypeHashMap> value, + AsyncCallback<HashMap<String, MarkerTypeHashMap>> callback); - void echo(LinkedHashMap<String, IsSerializable> value, - AsyncCallback<LinkedHashMap<String, IsSerializable>> callback); - - void echo(HashSet<IsSerializable> value, - AsyncCallback<HashSet<IsSerializable>> callback); + void echo(HashSet<MarkerTypeHashSet> value, + AsyncCallback<HashSet<MarkerTypeHashSet>> callback); void echo(int[] value, AsyncCallback<int[]> callback); void echo(Integer[] value, AsyncCallback<Integer[]> callback); + void echo(java.sql.Date[] value, AsyncCallback<java.sql.Date[]> callback); + + void echo(LinkedHashMap<String, MarkerTypeLinkedHashMap> value, + AsyncCallback<LinkedHashMap<String, MarkerTypeLinkedHashMap>> callback); + + void echo(LinkedHashSet<MarkerTypeLinkedHashSet> value, + AsyncCallback<LinkedHashSet<MarkerTypeLinkedHashSet>> callback); + void echo(long[] value, AsyncCallback<long[]> callback); void echo(Long[] value, AsyncCallback<Long[]> callback); @@ -85,9 +97,9 @@ void echo(Timestamp[] value, AsyncCallback<Timestamp[]> callback); - void echo(Vector<IsSerializable> value, - AsyncCallback<Vector<IsSerializable>> callback); + void echo(Vector<MarkerTypeVector> value, + AsyncCallback<Vector<MarkerTypeVector>> callback); - void echoArraysAsList(List<IsSerializable> value, - AsyncCallback<List<IsSerializable>> callback); + void echoArraysAsList(List<MarkerTypeArraysAsList> value, + AsyncCallback<List<MarkerTypeArraysAsList>> callback); }
diff --git a/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetFactory.java b/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetFactory.java index 71c67c2..86fa926 100644 --- a/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetFactory.java +++ b/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetFactory.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2008 Google Inc. * * 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 @@ -26,7 +26,7 @@ /** * Used to test an automatically serializable subclass of a manually - * serializable subtype + * serializable subtype. */ public static class SerializableSubclass extends ManuallySerializedClass implements IsSerializable {
diff --git a/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetValidator.java index ded6f14..cee790c 100644 --- a/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetValidator.java +++ b/user/test/com/google/gwt/user/client/rpc/CustomFieldSerializerTestSetValidator.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2008 Google Inc. * * 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 @@ -31,7 +31,7 @@ return manuallySerializedClass.getA() == 4 && manuallySerializedClass.getB() == 5 && manuallySerializedClass.getC() == 6 - && manuallySerializedClass.getObj().equals("bye"); + && manuallySerializedClass.getString().equals("bye"); } // Must be a non-null array with two == elements
diff --git a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass.java b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass.java index 2fa58ce..28069e4 100644 --- a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass.java +++ b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass.java
@@ -29,7 +29,7 @@ private int c = 3; - private Object obj = "hello"; + private String str = "hello"; public int getA() { return a; @@ -43,8 +43,8 @@ return c; } - public Object getObj() { - return obj; + public String getString() { + return str; } public void setA(int a) { @@ -59,7 +59,7 @@ this.c = c; } - public void setObj(Object obj) { - this.obj = obj; + public void setString(String str) { + this.str = str; } } \ No newline at end of file
diff --git a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass_CustomFieldSerializer.java b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass_CustomFieldSerializer.java index 1c9531d..f251207 100644 --- a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass_CustomFieldSerializer.java +++ b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedClass_CustomFieldSerializer.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2008 Google Inc. * * 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 @@ -26,7 +26,7 @@ instance.setA(streamReader.readInt()); instance.setB(streamReader.readInt()); instance.setC(streamReader.readInt()); - instance.setObj(streamReader.readString()); + instance.setString(streamReader.readString()); } public static void serialize(SerializationStreamWriter streamWriter,
diff --git a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedImmutableClass.java b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedImmutableClass.java index baa4518..ff407d0 100644 --- a/user/test/com/google/gwt/user/client/rpc/ManuallySerializedImmutableClass.java +++ b/user/test/com/google/gwt/user/client/rpc/ManuallySerializedImmutableClass.java
@@ -25,6 +25,13 @@ * factory. */ public class ManuallySerializedImmutableClass { + /** + * Ensures that RPC will consider Date to be exposed. It will be pruned by + * dead code elimination. + */ + @SuppressWarnings("unused") + private Date dateTypeExposeToSerialization; + private final Date endDate; private final Date startDate;
diff --git a/user/test/com/google/gwt/user/client/rpc/RemoteServiceServletTest.java b/user/test/com/google/gwt/user/client/rpc/RemoteServiceServletTest.java index 5ed9176..52251c8 100644 --- a/user/test/com/google/gwt/user/client/rpc/RemoteServiceServletTest.java +++ b/user/test/com/google/gwt/user/client/rpc/RemoteServiceServletTest.java
@@ -56,7 +56,9 @@ public void testAlternateStatusCode() { RemoteServiceServletTestServiceAsync service = getAsyncService(); ((ServiceDefTarget) service).setServiceEntryPoint(GWT.getModuleBaseURL() - + "404"); + + "servlettest/404"); + + delayTestFinish(TEST_DELAY); service.test(new AsyncCallback<Void>() { @@ -71,7 +73,7 @@ } public void onSuccess(Void result) { - fail(); + fail("Should not have succeeded"); } }); }
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java index d5da927..8bb6dd9 100644 --- a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java +++ b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
@@ -23,36 +23,148 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; /** - * TODO: document me. + * Creates test collections. */ public class TestSetFactory { /** - * TODO: document me. + * Base type for single-use marker types to independently check type parameter + * exposure in various collections. */ - public static class SerializableClass implements IsSerializable { - IsSerializable elementRef; + public static class MarkerBase implements IsSerializable { + public String value; - IsSerializable[] elements; - - public IsSerializable getElementRef() { - return elementRef; + public MarkerBase(String value) { + this.value = value; } - public IsSerializable[] getElements() { - return elements; + @Override + public boolean equals(Object obj) { + if (obj instanceof MarkerBase && obj.getClass() == this.getClass()) { + MarkerBase other = (MarkerBase) obj; + return value == other.value + || (value != null && value.equals(other.value)); + } + return false; } - public void setElementRef(IsSerializable elementRef) { - this.elementRef = elementRef; + @Override + public int hashCode() { + return value.hashCode(); } - public void setElements(IsSerializable[] elements) { - this.elements = elements; + @Override + public String toString() { + return value; + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeArrayList extends MarkerBase { + public MarkerTypeArrayList(String value) { + super(value); + } + + MarkerTypeArrayList() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeArraysAsList extends MarkerBase { + + public MarkerTypeArraysAsList(String value) { + super(value); + } + + MarkerTypeArraysAsList() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeHashMap extends MarkerBase { + + public MarkerTypeHashMap(String value) { + super(value); + } + + MarkerTypeHashMap() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeHashSet extends MarkerBase { + + public MarkerTypeHashSet(String value) { + super(value); + } + + MarkerTypeHashSet() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeLinkedHashMap extends MarkerBase { + + public MarkerTypeLinkedHashMap(String value) { + super(value); + } + + MarkerTypeLinkedHashMap() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeLinkedHashSet extends MarkerBase { + + public MarkerTypeLinkedHashSet(String value) { + super(value); + } + + MarkerTypeLinkedHashSet() { + super(null); + } + } + + /** + * A single-use marker type to independently check type parameter exposure in + * various collections. + */ + public static final class MarkerTypeVector extends MarkerBase { + + public MarkerTypeVector(String value) { + super(value); + } + + MarkerTypeVector() { + super(null); } } @@ -92,94 +204,13 @@ } /** - * TODO: document me. - */ - public static class SerializableList extends ArrayList implements - IsSerializable { - } - - /** - * TODO: document me. - */ - public static class SerializableMap extends HashMap implements IsSerializable { - } - - /** - * TODO: document me. - */ - public static class SerializableNode extends UnserializableNode implements - IsSerializable { - - protected String data; - - protected SerializableNode next; - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null) { - return false; - } - - if (!(obj instanceof SerializableNode)) { - return false; - } - - SerializableNode other = (SerializableNode) obj; - if (data != other.data) { - if (data == null || !data.equals(other.data)) { - return false; - } - } - - if (next != other.next) { - if (next == null || !next.equals(other.next)) { - return false; - } - } - - return true; - } - - public String getData() { - return data; - } - - public SerializableNode getNext() { - return next; - } - - public int hashCode() { - int hashValue = 0; - if (data != null) { - hashValue += data.hashCode(); - } - - if (next != null && next != this) { - hashValue += next.hashCode(); - } - - return hashValue; - } - - public void setData(String data) { - this.data = data; - } - - public void setNext(SerializableNode next) { - this.next = next; - } - } - - /** * Tests that classes with a private no-arg constructor can be serialized. */ public static class SerializablePrivateNoArg implements IsSerializable { private int value; public SerializablePrivateNoArg(int value) { + this(); this.value = value; } @@ -194,19 +225,6 @@ /** * TODO: document me. */ - public static class SerializableSet extends HashSet implements IsSerializable { - } - - /** - * TODO: document me. - */ - public static class SerializableVector extends Vector implements - IsSerializable { - } - - /** - * TODO: document me. - */ public static class SerializableWithTwoArrays implements IsSerializable { String[] one; String[] two; @@ -218,6 +236,22 @@ public static class UnserializableNode { } + public static ArrayList<MarkerTypeArrayList> createArrayList() { + ArrayList<MarkerTypeArrayList> list = new ArrayList<MarkerTypeArrayList>(); + list.add(new MarkerTypeArrayList("foo")); + list.add(new MarkerTypeArrayList("bar")); + list.add(new MarkerTypeArrayList("baz")); + list.add(new MarkerTypeArrayList("bal")); + list.add(new MarkerTypeArrayList("w00t")); + return list; + } + + public static List<MarkerTypeArraysAsList> createArraysAsList() { + return Arrays.asList(new MarkerTypeArraysAsList("foo"), + new MarkerTypeArraysAsList("bar"), new MarkerTypeArraysAsList("baz"), + new MarkerTypeArraysAsList("bal"), new MarkerTypeArraysAsList("w00t")); + } + public static Boolean[] createBooleanArray() { return new Boolean[] { Boolean.valueOf(true), Boolean.valueOf(false), Boolean.valueOf(true), @@ -236,6 +270,7 @@ new Character(Character.MAX_VALUE), new Character(Character.MIN_VALUE)}; } + @SuppressWarnings("deprecation") public static Date[] createDateArray() { return new Date[] { new Date(1992 - 1900, 9, 18), new Date(1997 - 1900, 6, 6)}; @@ -253,45 +288,23 @@ new Float(Float.MAX_VALUE), new Float(Float.MIN_VALUE)}; } - public static HashMap createHashMap() { - HashMap map = new HashMap(); - map.put("SerializableNode", new SerializableNode()); - map.put("SerializableList", new SerializableList()); - map.put("SerializableMap", new SerializableMap()); - map.put("SerializableSet", new SerializableSet()); - map.put("SerializableVector", new SerializableVector()); + public static HashMap<String, MarkerTypeHashMap> createHashMap() { + HashMap<String, MarkerTypeHashMap> map = new HashMap<String, MarkerTypeHashMap>(); + map.put("foo", new MarkerTypeHashMap("foo")); + map.put("bar", new MarkerTypeHashMap("bar")); + map.put("baz", new MarkerTypeHashMap("baz")); + map.put("bal", new MarkerTypeHashMap("bal")); + map.put("w00t", new MarkerTypeHashMap("w00t")); return map; } - public static LinkedHashMap createLRULinkedHashMap() { - LinkedHashMap map = new LinkedHashMap(100, 1.0f, true); - map.put("SerializableNode", new SerializableNode()); - map.put("SerializableList", new SerializableList()); - map.put("SerializableMap", new SerializableMap()); - map.put("SerializableSet", new SerializableSet()); - map.put("SerializableVector", new SerializableVector()); - map.get("SerializableMap"); - return map; - } - - public static LinkedHashMap createLinkedHashMap() { - LinkedHashMap map = new LinkedHashMap(); - map.put("SerializableNode", new SerializableNode()); - map.put("SerializableList", new SerializableList()); - map.put("SerializableMap", new SerializableMap()); - map.put("SerializableSet", new SerializableSet()); - map.put("SerializableVector", new SerializableVector()); - return map; - } - - public static HashSet createHashSet() { - HashSet set = new HashSet(); - set.add(new SerializableNode()); - set.add(new SerializableList()); - set.add(new SerializableMap()); - set.add(new SerializableSet()); - set.add(new SerializableVector()); - + public static HashSet<MarkerTypeHashSet> createHashSet() { + HashSet<MarkerTypeHashSet> set = new HashSet<MarkerTypeHashSet>(); + set.add(new MarkerTypeHashSet("foo")); + set.add(new MarkerTypeHashSet("bar")); + set.add(new MarkerTypeHashSet("baz")); + set.add(new MarkerTypeHashSet("bal")); + set.add(new MarkerTypeHashSet("w00t")); return set; } @@ -301,12 +314,43 @@ new Integer(Integer.MAX_VALUE), new Integer(Integer.MIN_VALUE)}; } + public static LinkedHashMap<String, MarkerTypeLinkedHashMap> createLinkedHashMap() { + LinkedHashMap<String, MarkerTypeLinkedHashMap> map = new LinkedHashMap<String, MarkerTypeLinkedHashMap>(); + map.put("foo", new MarkerTypeLinkedHashMap("foo")); + map.put("bar", new MarkerTypeLinkedHashMap("bar")); + map.put("baz", new MarkerTypeLinkedHashMap("baz")); + map.put("bal", new MarkerTypeLinkedHashMap("bal")); + map.put("w00t", new MarkerTypeLinkedHashMap("w00t")); + return map; + } + + public static LinkedHashSet<MarkerTypeLinkedHashSet> createLinkedHashSet() { + LinkedHashSet<MarkerTypeLinkedHashSet> set = new LinkedHashSet<MarkerTypeLinkedHashSet>(); + set.add(new MarkerTypeLinkedHashSet("foo")); + set.add(new MarkerTypeLinkedHashSet("bar")); + set.add(new MarkerTypeLinkedHashSet("baz")); + set.add(new MarkerTypeLinkedHashSet("bal")); + set.add(new MarkerTypeLinkedHashSet("w00t")); + return set; + } + public static Long[] createLongArray() { return new Long[] { new Long(Long.MAX_VALUE), new Long(Long.MIN_VALUE), new Long(Long.MAX_VALUE), new Long(Long.MIN_VALUE)}; } + public static LinkedHashMap<String, MarkerTypeLinkedHashMap> createLRULinkedHashMap() { + LinkedHashMap<String, MarkerTypeLinkedHashMap> map = new LinkedHashMap<String, MarkerTypeLinkedHashMap>( + 100, 1.0f, true); + map.put("foo", new MarkerTypeLinkedHashMap("foo")); + map.put("bar", new MarkerTypeLinkedHashMap("bar")); + map.put("baz", new MarkerTypeLinkedHashMap("baz")); + map.put("bal", new MarkerTypeLinkedHashMap("bal")); + map.put("w00t", new MarkerTypeLinkedHashMap("w00t")); + return map; + } + public static boolean[] createPrimitiveBooleanArray() { return new boolean[] {true, true, false, false, true, false}; } @@ -381,13 +425,13 @@ "valueOf", "constructor", "__proto__"}; } - public static Vector createVector() { - Vector vector = new Vector(); - vector.add(new SerializableNode()); - vector.add(new SerializableList()); - vector.add(new SerializableMap()); - vector.add(new SerializableSet()); - vector.add(new SerializableVector()); + public static Vector<MarkerTypeVector> createVector() { + Vector<MarkerTypeVector> vector = new Vector<MarkerTypeVector>(); + vector.add(new MarkerTypeVector("foo")); + vector.add(new MarkerTypeVector("bar")); + vector.add(new MarkerTypeVector("baz")); + vector.add(new MarkerTypeVector("bal")); + vector.add(new MarkerTypeVector("w00t")); return vector; } @@ -411,20 +455,6 @@ return head; } - static ArrayList createArrayList() { - ArrayList list = new ArrayList(); - list.add(new SerializableNode()); - list.add(new SerializableList()); - list.add(new SerializableMap()); - list.add(new SerializableSet()); - list.add(new SerializableVector()); - return list; - } - - static List createArraysAsList() { - return Arrays.asList((byte) 0, (byte) 1, (byte) 2, (byte) 3); - } - static SerializableDoublyLinkedNode createComplexCyclicGraph() { SerializableDoublyLinkedNode n1 = new SerializableDoublyLinkedNode(); n1.setData("n0"); @@ -456,18 +486,6 @@ return o; } - static SerializableClass createSerializableClass() { - SerializableClass cls = new SerializableClass(); - IsSerializable[] elements = new IsSerializable[] { - new SerializableClass(), new SerializableClass(), - new SerializableClass(), new SerializableClass(),}; - - cls.setElements(elements); - cls.setElementRef(elements[3]); - - return cls; - } - static SerializableDoublyLinkedNode createTrivialCyclicGraph() { SerializableDoublyLinkedNode root = new SerializableDoublyLinkedNode(); root.setData("head");
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java index d210669..da95a6d 100644 --- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java +++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
@@ -15,7 +15,6 @@ */ package com.google.gwt.user.client.rpc; -import com.google.gwt.user.client.rpc.TestSetFactory.SerializableClass; import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode; import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg; import com.google.gwt.user.client.rpc.TestSetFactory.SerializableWithTwoArrays; @@ -25,8 +24,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.Map.Entry; @@ -36,15 +35,6 @@ */ public class TestSetValidator { - public static boolean equals(Iterator expected, Iterator actual) { - while (expected.hasNext() && actual.hasNext()) { - if (!expected.next().equals(actual.next())) { - return false; - } - } - return expected.hasNext() == actual.hasNext(); - } - public static boolean equals(boolean[] expected, boolean[] actual) { if (actual == null) { return false; @@ -153,6 +143,15 @@ return true; } + public static boolean equals(Iterator expected, Iterator actual) { + while (expected.hasNext() && actual.hasNext()) { + if (!expected.next().equals(actual.next())) { + return false; + } + } + return expected.hasNext() == actual.hasNext(); + } + public static boolean equals(long[] expected, long[] actual) { if (actual == null) { return false; @@ -235,28 +234,7 @@ return reference.equals(list); } - public static boolean isValid(HashSet expected, HashSet actual) { - if (actual == null) { - return false; - } - - if (expected.size() != actual.size()) { - return false; - } - - Iterator entryIter = expected.iterator(); - while (entryIter.hasNext()) { - Object entry = entryIter.next(); - - if (!actual.contains(entry)) { - return false; - } - } - - return true; - } - - public static boolean isValid(Map expected, HashMap map) { + public static boolean isValid(HashMap expected, HashMap map) { if (map == null) { return false; } @@ -286,8 +264,29 @@ return true; } + public static boolean isValid(HashSet expected, HashSet actual) { + if (actual == null) { + return false; + } + + if (expected.size() != actual.size()) { + return false; + } + + Iterator entryIter = expected.iterator(); + while (entryIter.hasNext()) { + Object entry = entryIter.next(); + + if (!actual.contains(entry)) { + return false; + } + } + + return true; + } + public static boolean isValid(LinkedHashMap expected, LinkedHashMap map) { - if (isValid((Map) expected, (HashMap) map)) { + if (isValid((HashMap) expected, (HashMap) map)) { Iterator expectedEntries = expected.entrySet().iterator(); Iterator actualEntries = map.entrySet().iterator(); return equals(expectedEntries, actualEntries); @@ -295,27 +294,13 @@ return false; } - public static boolean isValid(SerializableClass actual) { - if (actual == null) { - return false; + public static boolean isValid(LinkedHashSet expected, LinkedHashSet map) { + if (isValid((HashSet) expected, (HashSet) map)) { + Iterator expectedEntries = expected.iterator(); + Iterator actualEntries = map.iterator(); + return equals(expectedEntries, actualEntries); } - - IsSerializable[] elements = actual.getElements(); - IsSerializable elementRef = actual.getElementRef(); - - if (elements == null || elementRef == null) { - return false; - } - - if (elements.length != 4) { - return false; - } - - if (elements[3] != elementRef) { - return false; - } - - return true; + return false; } public static boolean isValid(SerializablePrivateNoArg actual) {
diff --git a/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java b/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java index 972c2b1..e72c6ec 100644 --- a/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java +++ b/user/test/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilderTest.java
@@ -30,6 +30,8 @@ import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType; import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.dev.cfg.ModuleDefLoader; +import com.google.gwt.dev.cfg.Property; +import com.google.gwt.dev.cfg.StaticPropertyOracle; import com.google.gwt.dev.javac.CompilationUnit; import com.google.gwt.dev.javac.JavaSourceCodeBase; import com.google.gwt.dev.javac.MockCompilationUnit; @@ -38,7 +40,6 @@ import com.google.gwt.dev.util.log.PrintWriterTreeLogger; import com.google.gwt.user.rebind.rpc.testcases.client.AbstractSerializableTypes; import com.google.gwt.user.rebind.rpc.testcases.client.ClassWithTypeParameterThatErasesToObject; -import com.google.gwt.user.rebind.rpc.testcases.client.CovariantArrays; import com.google.gwt.user.rebind.rpc.testcases.client.ManualSerialization; import com.google.gwt.user.rebind.rpc.testcases.client.NoSerializableTypes; import com.google.gwt.user.rebind.rpc.testcases.client.NotAllSubtypesAreSerializable; @@ -231,6 +232,14 @@ return new MockCompilationUnit(qname, code.toString()); } + private static SerializableTypeOracleBuilder createSerializableTypeOracleBuilder( + TreeLogger logger, TypeOracle to) throws UnableToCompleteException { + StaticPropertyOracle propertyOracle = new StaticPropertyOracle(); + // PropertyOracle has no values. + propertyOracle.setPropertyValues(new Property[0], new String[0]); + return new SerializableTypeOracleBuilder(logger, propertyOracle, to); + } + private static TypeInfo[] getActualTypeInfo(SerializableTypeOracle sto) { JType[] types = sto.getSerializableTypes(); TypeInfo[] actual = new TypeInfo[types.length]; @@ -351,7 +360,7 @@ JParameterizedType listOfCantSerialize = to.getParameterizedType(list, makeArray(cantSerialize)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, listOfCantSerialize); SerializableTypeOracle so = sob.build(logger); @@ -402,7 +411,7 @@ JClassType b = to.getType("B"); JClassType c = to.getType("C"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, b); SerializableTypeOracle so = sob.build(logger); @@ -458,7 +467,7 @@ JClassType c = to.getType("java.C"); JArrayType arrayOfC = to.getArrayType(c); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, arrayOfA); SerializableTypeOracle so = sob.build(logger); @@ -550,7 +559,7 @@ JClassType ser2 = to.getType("Ser2"); JClassType root = to.getType("Root"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, root); @@ -631,7 +640,7 @@ JClassType javaLangString = to.getType(String.class.getName()); JParameterizedType cOfString = to.getParameterizedType(c, makeArray(javaLangString)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, cOfString); @@ -778,7 +787,7 @@ TreeLogger logger = createLogger(); TypeOracle to = TypeOracleTestingUtils.buildTypeOracle(logger, units); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); // Does not qualify because it is not declared to be auto or manually @@ -853,7 +862,7 @@ ClassWithTypeParameterThatErasesToObject.class.getCanonicalName()).isGenericType().getRawType(); // The raw form of the type should not be serializable. - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, rawType); try { @@ -925,7 +934,7 @@ JClassType dateHolder = to.getType("DateHolder"); JClassType unrelatedClass = to.getType("UnrelatedClass"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, holder.getRawType()); SerializableTypeOracle so = sob.build(logger); @@ -949,31 +958,60 @@ */ public void testCovariantArrays() throws UnableToCompleteException, NotFoundException { - TreeLogger logger = createLogger(); + Set<CompilationUnit> units = new HashSet<CompilationUnit>(); + addStandardClasses(units); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( - logger, typeOracle); - JClassType rootType = typeOracle.getArrayType(typeOracle.getType(CovariantArrays.AA.class.getCanonicalName())); - stob.addRootType(logger, rootType); + { + StringBuilder code = new StringBuilder(); + code.append("import java.io.Serializable;\n"); + code.append("public class Sup implements Serializable {\n"); + code.append("}\n"); + units.add(createMockCompilationUnit("Sup", code)); + } + + { + StringBuilder code = new StringBuilder(); + code.append("import java.io.Serializable;\n"); + code.append("public class Sub extends Sup {\n"); + code.append("}\n"); + units.add(createMockCompilationUnit("Sub", code)); + } + + TreeLogger logger = createLogger(); + TypeOracle to = TypeOracleTestingUtils.buildTypeOracle(logger, units); + + JClassType sup = to.getType("Sup"); + JClassType sub = to.getType("Sub"); + JPrimitiveType primFloat = JPrimitiveType.FLOAT; + + JArrayType subArray = to.getArrayType(sub); + JArrayType subArrayArray = to.getArrayType(subArray); + JArrayType supArray = to.getArrayType(sup); + JArrayType supArrayArray = to.getArrayType(supArray); + JArrayType primFloatArray = to.getArrayType(primFloat); + JArrayType primFloatArrayArray = to.getArrayType(primFloatArray); + + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( + logger, to); + // adding Sub first exercises an extra code path in STOB + stob.addRootType(logger, sub); + stob.addRootType(logger, supArrayArray); + stob.addRootType(logger, primFloatArrayArray); SerializableTypeOracle sto = stob.build(logger); - TypeInfo[] expected = new TypeInfo[] { - new TypeInfo(CovariantArrays.AA.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.BB.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.CC.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.DD.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.A.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.B.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.B.class.getName(), true), - new TypeInfo(CovariantArrays.C.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.D.class.getName() + "[]", true), - new TypeInfo(CovariantArrays.D.class.getName(), true),}; - validateSTO(sto, expected); + assertSerializableTypes(sto, sup, sub, supArray, subArray, primFloatArray, + supArrayArray, subArrayArray, primFloatArrayArray); + assertInstantiable(sto, primFloatArrayArray); + assertInstantiable(sto, primFloatArray); + assertInstantiable(sto, subArrayArray); + assertInstantiable(sto, subArray); + assertInstantiable(sto, supArrayArray); + assertInstantiable(sto, supArray); } /** * If the query type extends a raw type, be sure to pick up the parameters of - * the raw supertype. + * the raw subertype. * * @throws UnableToCompleteException * @throws NotFoundException @@ -1024,7 +1062,7 @@ JClassType serClass = to.getType("SerClass"); JClassType serClassSub = to.getType("SerClassSub"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, nameSet); SerializableTypeOracle so = sob.build(logger); @@ -1110,7 +1148,7 @@ JParameterizedType hashSetOfString = to.getParameterizedType(hashSet, makeArray(string)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, hashSetOfString); SerializableTypeOracle so = sob.build(logger); @@ -1171,7 +1209,7 @@ JParameterizedType aOfString = to.getParameterizedType(a, makeArray(serializableArgument)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, aOfString); SerializableTypeOracle so = sob.build(logger); @@ -1226,7 +1264,7 @@ JParameterizedType aOfString = to.getParameterizedType(a, makeArray(unusedSerializableArgument)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, aOfString); SerializableTypeOracle so = sob.build(logger); @@ -1274,7 +1312,7 @@ JClassType javaLangString = to.getType(String.class.getName()); JParameterizedType aOfString = to.getParameterizedType(a, makeArray(javaLangString)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, aOfString); SerializableTypeOracle so = sob.build(logger); @@ -1322,7 +1360,7 @@ JClassType javaLangString = to.getType(String.class.getName()); JParameterizedType aOfString = to.getParameterizedType(a, makeArray(javaLangString)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); assertEquals(EXPOSURE_DIRECT, sob.getTypeParameterExposure(a, 0)); @@ -1348,7 +1386,7 @@ UnableToCompleteException { TreeLogger logger = createLogger(); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); JClassType a = typeOracle.getType(ManualSerialization.A.class.getCanonicalName()); JClassType b = typeOracle.getType(ManualSerialization.B.class.getCanonicalName()); @@ -1367,7 +1405,7 @@ TreeLogger logger = createLogger(); JClassType rawList = typeOracle.getType(List.class.getName()); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, rawList); SerializableTypeOracle sto = stob.build(logger); @@ -1492,7 +1530,7 @@ JParameterizedType parameterizedListOfIntf1 = to.getParameterizedType(list, makeArray(intf1)); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, parameterizedListOfIntf1); SerializableTypeOracle so = sob.build(logger); @@ -1511,7 +1549,7 @@ TreeLogger logger = createLogger(); JClassType a = typeOracle.getType(NoSerializableTypes.A.class.getCanonicalName()); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, a); try { @@ -1532,7 +1570,7 @@ TreeLogger logger = createLogger(); JClassType a = typeOracle.getType(NotAllSubtypesAreSerializable.A.class.getCanonicalName()); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, a); SerializableTypeOracle sto = stob.build(logger); @@ -1554,7 +1592,7 @@ TreeLogger logger = createLogger(); JArrayType objectArray = typeOracle.getArrayType(typeOracle.getJavaLangObject()); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, objectArray); try { @@ -1571,7 +1609,7 @@ public void testObjectNotInstantiable() throws UnableToCompleteException { TreeLogger logger = createLogger(); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType(logger, typeOracle.getJavaLangObject()); try { @@ -1590,7 +1628,7 @@ throws UnableToCompleteException, NotFoundException { TreeLogger logger = createLogger(); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, typeOracle); stob.addRootType( logger, @@ -1655,7 +1693,7 @@ JGenericType linkedList = to.getType("LinkedList").isGenericType(); JClassType randomClass = to.getType("RandomClass"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, list.getRawType()); SerializableTypeOracle so = sob.build(logger); @@ -1701,7 +1739,7 @@ JClassType serializableClass = to.getType("SerializableClass"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, rawA); SerializableTypeOracle so = sob.build(logger); @@ -1738,7 +1776,7 @@ JClassType rawA = a.getRawType(); JTypeParameter ta = a.getTypeParameters()[0]; - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, ta); SerializableTypeOracle so = sob.build(logger); @@ -1801,7 +1839,7 @@ JClassType javaLangString = to.getType(String.class.getName()); JParameterizedType aOfString = to.getParameterizedType(a, makeArray(javaLangString)); - SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder stob = createSerializableTypeOracleBuilder( logger, to); stob.addRootType(logger, aOfString); @@ -1861,7 +1899,7 @@ JRawType rawB = to.getType("B").isGenericType().getRawType(); JClassType c = to.getType("C"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, a); SerializableTypeOracle so = sob.build(logger); @@ -1925,7 +1963,7 @@ new JClassType[] {to.getType(String.class.getName())}); JClassType ser = to.getType("Ser"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, intfOfString); SerializableTypeOracle so = sob.build(logger); @@ -1973,7 +2011,7 @@ JClassType a = to.getType("A"); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, a); SerializableTypeOracle so = sob.build(logger); @@ -2150,7 +2188,7 @@ JParameterizedType parameterizedType = to.getParameterizedType(a, new JClassType[] {syntheticTypeParam}); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, parameterizedType); SerializableTypeOracle so = sob.build(logger); @@ -2205,7 +2243,7 @@ JTypeParameter u = a.getTypeParameters()[0]; JTypeParameter v = a.getMethod("getFoo", makeArray()).getReturnType().isTypeParameter(); - SerializableTypeOracleBuilder sob = new SerializableTypeOracleBuilder( + SerializableTypeOracleBuilder sob = createSerializableTypeOracleBuilder( logger, to); sob.addRootType(logger, u); sob.addRootType(logger, v);
diff --git a/user/test/com/google/gwt/user/rebind/rpc/testcases/client/CovariantArrays.java b/user/test/com/google/gwt/user/rebind/rpc/testcases/client/CovariantArrays.java deleted file mode 100644 index f4f5c6b..0000000 --- a/user/test/com/google/gwt/user/rebind/rpc/testcases/client/CovariantArrays.java +++ /dev/null
@@ -1,85 +0,0 @@ -/* - * Copyright 2007 Google Inc. - * - * 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.user.rebind.rpc.testcases.client; - -import com.google.gwt.user.client.rpc.IsSerializable; - -/** - * Used to test that the - * {@link com.google.gwt.user.rebind.rpc.SerializableTypeOracleBuilder SerializableTypeOracleBuilder} - * will handle covariant arrays correctly. For example, the service interface - * below should be able to handle the following covariant array types: AA[], - * A[], BB[], B[], CC[], C[], DD[], D[]. Notice that E[] should not be included. - */ -public interface CovariantArrays { - /** - * Not serializable. - */ - class A implements DD { - } - - /** - * Not serializable. - */ - interface AA { - } - - /** - * Auto serializable. - */ - class B extends A implements IsSerializable { - } - - /** - * Not serializable. - */ - interface BB extends AA { - } - - /** - * Not auto serializable due to bad field. - */ - class C extends B { - Object field; - } - - /** - * Not serializable. - */ - interface CC extends AA { - } - - /** - * Auto serializable. - */ - class D extends C implements IsSerializable { - } - - /** - * Not serializable. - */ - interface DD extends BB, CC { - } - - /** - * Not auto serializable because super class is not. - */ - class E extends C { - } - - AA[] getAs(); -}
diff --git a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java index cd61558..12bd35b 100644 --- a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java +++ b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
@@ -18,6 +18,13 @@ import com.google.gwt.user.client.rpc.CollectionsTestService; import com.google.gwt.user.client.rpc.TestSetFactory; import com.google.gwt.user.client.rpc.TestSetValidator; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashSet; +import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector; import java.sql.Time; import java.sql.Timestamp; @@ -27,6 +34,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; @@ -40,8 +48,8 @@ return Arrays.asList(values).toString(); } - @SuppressWarnings("unchecked") - public ArrayList echo(ArrayList list) throws CollectionsTestServiceException { + public ArrayList<MarkerTypeArrayList> echo(ArrayList<MarkerTypeArrayList> list) + throws CollectionsTestServiceException { if (!TestSetValidator.isValid(list)) { throw new CollectionsTestServiceException(); } @@ -122,17 +130,6 @@ return actual; } - public java.sql.Date[] echo(java.sql.Date[] actual) - throws CollectionsTestServiceException { - java.sql.Date[] expected = TestSetFactory.createSqlDateArray(); - if (!TestSetValidator.equals(expected, actual)) { - throw new CollectionsTestServiceException("expected: " - + toString(expected) + " actual: " + toString(actual)); - } - - return actual; - } - public double[] echo(double[] actual) throws CollectionsTestServiceException { double[] expected = TestSetFactory.createPrimitiveDoubleArray(); if (!TestSetValidator.equals(expected, actual)) { @@ -173,9 +170,10 @@ return actual; } - @SuppressWarnings("unchecked") - public HashMap echo(HashMap actual) throws CollectionsTestServiceException { - HashMap expected = TestSetFactory.createHashMap(); + public HashMap<String, MarkerTypeHashMap> echo( + HashMap<String, MarkerTypeHashMap> actual) + throws CollectionsTestServiceException { + HashMap<String, MarkerTypeHashMap> expected = TestSetFactory.createHashMap(); if (!TestSetValidator.isValid(expected, actual)) { throw new CollectionsTestServiceException("expected: " + expected.toString() + " actual: " + actual.toString()); @@ -184,20 +182,9 @@ return actual; } - @SuppressWarnings("unchecked") - public LinkedHashMap echo(LinkedHashMap actual) + public HashSet<MarkerTypeHashSet> echo(HashSet<MarkerTypeHashSet> actual) throws CollectionsTestServiceException { - HashMap expected = TestSetFactory.createLinkedHashMap(); - if (!TestSetValidator.isValid(expected, actual)) { - throw new CollectionsTestServiceException("expected:" - + expected.toString() + " actual:" + actual.toString()); - } - return actual; - } - - @SuppressWarnings("unchecked") - public HashSet echo(HashSet actual) throws CollectionsTestServiceException { - HashSet expected = TestSetFactory.createHashSet(); + HashSet<MarkerTypeHashSet> expected = TestSetFactory.createHashSet(); if (!TestSetValidator.isValid(expected, actual)) { throw new CollectionsTestServiceException("expected: " + expected.toString() + " actual: " + actual.toString()); @@ -232,6 +219,39 @@ return actual; } + public java.sql.Date[] echo(java.sql.Date[] actual) + throws CollectionsTestServiceException { + java.sql.Date[] expected = TestSetFactory.createSqlDateArray(); + if (!TestSetValidator.equals(expected, actual)) { + throw new CollectionsTestServiceException("expected: " + + toString(expected) + " actual: " + toString(actual)); + } + + return actual; + } + + public LinkedHashMap<String, MarkerTypeLinkedHashMap> echo( + LinkedHashMap<String, MarkerTypeLinkedHashMap> actual) + throws CollectionsTestServiceException { + LinkedHashMap<String, MarkerTypeLinkedHashMap> expected = TestSetFactory.createLinkedHashMap(); + if (!TestSetValidator.isValid(expected, actual)) { + throw new CollectionsTestServiceException("expected: " + + expected.toString() + " actual: " + actual.toString()); + } + return actual; + } + + public LinkedHashSet<MarkerTypeLinkedHashSet> echo( + LinkedHashSet<MarkerTypeLinkedHashSet> actual) + throws CollectionsTestServiceException { + LinkedHashSet<MarkerTypeLinkedHashSet> expected = TestSetFactory.createLinkedHashSet(); + if (!TestSetValidator.isValid(expected, actual)) { + throw new CollectionsTestServiceException("expected: " + + expected.toString() + " actual: " + actual.toString()); + } + return actual; + } + public long[] echo(long[] actual) throws CollectionsTestServiceException { long[] expected = TestSetFactory.createPrimitiveLongArray(); if (!TestSetValidator.equals(expected, actual)) { @@ -308,9 +328,9 @@ return actual; } - @SuppressWarnings("unchecked") - public Vector echo(Vector actual) throws CollectionsTestServiceException { - Vector expected = TestSetFactory.createVector(); + public Vector<MarkerTypeVector> echo(Vector<MarkerTypeVector> actual) + throws CollectionsTestServiceException { + Vector<MarkerTypeVector> expected = TestSetFactory.createVector(); if (!TestSetValidator.isValid(expected, actual)) { throw new CollectionsTestServiceException("expected: " + expected.toString() + " actual: " + actual.toString()); @@ -319,12 +339,8 @@ return actual; } - /** - * Return the result of Arrays.asList(Object[]) to force an - * InvocationException on the client. - */ - @SuppressWarnings("unchecked") - public List echoArraysAsList(List value) + public List<MarkerTypeArraysAsList> echoArraysAsList( + List<MarkerTypeArraysAsList> value) throws CollectionsTestServiceException { if (!TestSetValidator.isValidAsList(value)) { throw new CollectionsTestServiceException();
diff --git a/user/test/com/google/gwt/user/server/rpc/CustomFieldSerializerTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/CustomFieldSerializerTestServiceImpl.java index 46205ba..ea5d3ce 100644 --- a/user/test/com/google/gwt/user/server/rpc/CustomFieldSerializerTestServiceImpl.java +++ b/user/test/com/google/gwt/user/server/rpc/CustomFieldSerializerTestServiceImpl.java
@@ -17,10 +17,13 @@ import com.google.gwt.user.client.rpc.CustomFieldSerializerTestService; import com.google.gwt.user.client.rpc.CustomFieldSerializerTestSetValidator; +import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; import com.google.gwt.user.client.rpc.ManuallySerializedClass; import com.google.gwt.user.client.rpc.ManuallySerializedImmutableClass; import com.google.gwt.user.client.rpc.CustomFieldSerializerTestSetFactory.SerializableSubclass; +import javax.servlet.ServletContext; + /** * Servlet used by the * {@link com.google.gwt.user.client.rpc.CustomFieldSerializerTest CustomFieldSerializerTest} @@ -29,6 +32,12 @@ public class CustomFieldSerializerTestServiceImpl extends RemoteServiceServlet implements CustomFieldSerializerTestService { + /** + * Filters log messages to avoid logging spurious warnings during successful + * tests. + */ + private ServletContext wrappedServletContext; + public ManuallySerializedClass echo( ManuallySerializedClass unserializableClass) { if (!CustomFieldSerializerTestSetValidator.isValid(unserializableClass)) { @@ -54,4 +63,26 @@ return serializableClass; } + + /** + * Overrides the default servlet context to filter expected log messages. + */ + @Override + public ServletContext getServletContext() { + if (wrappedServletContext == null) { + wrappedServletContext = new LogFilterServletContext( + super.getServletContext()) { + @Override + protected boolean shouldLog(Throwable t, String msg) { + if (t instanceof IncompatibleRemoteServiceException + && t.getMessage().contains( + "com.google.gwt.user.client.rpc.CustomFieldSerializerTestSetFactory$UnserializableSubclass")) { + return false; + } + return true; + } + }; + } + return wrappedServletContext; + } }
diff --git a/user/test/com/google/gwt/user/server/rpc/InheritanceTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/InheritanceTestServiceImpl.java index 77545da..5292afd 100644 --- a/user/test/com/google/gwt/user/server/rpc/InheritanceTestServiceImpl.java +++ b/user/test/com/google/gwt/user/server/rpc/InheritanceTestServiceImpl.java
@@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2008 Google Inc. * * 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 @@ -15,17 +15,21 @@ */ package com.google.gwt.user.server.rpc; +import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; +import com.google.gwt.user.client.rpc.InheritanceTestServiceSubtype; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory; import com.google.gwt.user.client.rpc.InheritanceTestSetValidator; -import com.google.gwt.user.client.rpc.InheritanceTestServiceSubtype; +import com.google.gwt.user.client.rpc.SerializationException; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.AbstractClass; -import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.MySerializableInterface; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.AnonymousClassInterface; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.Circle; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.JavaSerializableClass; +import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.MySerializableInterface; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.SerializableClass; import com.google.gwt.user.client.rpc.InheritanceTestSetFactory.SerializableClassWithTransientField; +import javax.servlet.ServletContext; + /** * Servlet used by the * {@link com.google.gwt.user.client.rpc.InheritanceTest InheritanceTest} unit @@ -34,6 +38,12 @@ public class InheritanceTestServiceImpl extends RemoteServiceServlet implements InheritanceTestServiceSubtype { + /** + * Filters log messages to avoid logging spurious warnings during successful + * tests. + */ + private ServletContext wrappedServletContext; + public AnonymousClassInterface echo(AnonymousClassInterface serializable) { return serializable; } @@ -85,6 +95,29 @@ return null; } + /** + * Overrides the default servlet context to filter expected log messages. + */ + @Override + public ServletContext getServletContext() { + if (wrappedServletContext == null) { + wrappedServletContext = new LogFilterServletContext( + super.getServletContext()) { + @Override + protected boolean shouldLog(Throwable t, String msg) { + if ((t instanceof IncompatibleRemoteServiceException || t instanceof SerializationException) + && (t.getMessage().contains("com.google.gwt.user.client.rpc.InheritanceTest$1")) + || t.getMessage().contains( + "com.google.gwt.user.client.rpc.InheritanceTestSetFactory$1")) { + return false; + } + return true; + } + }; + } + return wrappedServletContext; + } + public SerializableClass getUnserializableClass() { return InheritanceTestSetFactory.createNonStaticInnerClass(); }
diff --git a/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTest.java b/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTest.java index 04fefc9..c881d1b 100644 --- a/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTest.java +++ b/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTest.java
@@ -20,18 +20,13 @@ import junit.framework.TestCase; -import java.io.BufferedReader; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; -import java.security.Principal; import java.util.Enumeration; -import java.util.Locale; -import java.util.Map; import java.util.Set; import javax.servlet.RequestDispatcher; @@ -39,10 +34,6 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; /** * Test some of the failure modes associated with @@ -61,224 +52,14 @@ private static class Foo implements IsSerializable { } - private static class MockHttpServletRequest implements HttpServletRequest { + private class MockHttpServletRequestContextPath extends + MockHttpServletRequest { private String contextPath; - - public Object getAttribute(String arg0) { - throw new UnsupportedOperationException(); - } - - public Enumeration getAttributeNames() { - throw new UnsupportedOperationException(); - } - - public String getAuthType() { - throw new UnsupportedOperationException(); - } - - public String getCharacterEncoding() { - throw new UnsupportedOperationException(); - } - - public int getContentLength() { - throw new UnsupportedOperationException(); - } - - public String getContentType() { - throw new UnsupportedOperationException(); - } - + + @Override public String getContextPath() { return contextPath; } - - public Cookie[] getCookies() { - throw new UnsupportedOperationException(); - } - - public long getDateHeader(String arg0) { - throw new UnsupportedOperationException(); - } - - public String getHeader(String arg0) { - throw new UnsupportedOperationException(); - } - - public Enumeration getHeaderNames() { - throw new UnsupportedOperationException(); - } - - public Enumeration getHeaders(String arg0) { - throw new UnsupportedOperationException(); - } - - public ServletInputStream getInputStream() throws IOException { - throw new UnsupportedOperationException(); - } - - public int getIntHeader(String arg0) { - throw new UnsupportedOperationException(); - } - - public String getLocalAddr() { - throw new UnsupportedOperationException(); - } - - public Locale getLocale() { - throw new UnsupportedOperationException(); - } - - public Enumeration getLocales() { - throw new UnsupportedOperationException(); - } - - public String getLocalName() { - throw new UnsupportedOperationException(); - } - - public int getLocalPort() { - throw new UnsupportedOperationException(); - } - - public String getMethod() { - throw new UnsupportedOperationException(); - } - - public String getParameter(String arg0) { - throw new UnsupportedOperationException(); - } - - public Map getParameterMap() { - throw new UnsupportedOperationException(); - } - - public Enumeration getParameterNames() { - throw new UnsupportedOperationException(); - } - - public String[] getParameterValues(String arg0) { - throw new UnsupportedOperationException(); - } - - public String getPathInfo() { - throw new UnsupportedOperationException(); - } - - public String getPathTranslated() { - throw new UnsupportedOperationException(); - } - - public String getProtocol() { - throw new UnsupportedOperationException(); - } - - public String getQueryString() { - throw new UnsupportedOperationException(); - } - - public BufferedReader getReader() throws IOException { - throw new UnsupportedOperationException(); - } - - public String getRealPath(String arg0) { - throw new UnsupportedOperationException(); - } - - public String getRemoteAddr() { - throw new UnsupportedOperationException(); - } - - public String getRemoteHost() { - throw new UnsupportedOperationException(); - } - - public int getRemotePort() { - throw new UnsupportedOperationException(); - } - - public String getRemoteUser() { - throw new UnsupportedOperationException(); - } - - public RequestDispatcher getRequestDispatcher(String arg0) { - throw new UnsupportedOperationException(); - } - - public String getRequestedSessionId() { - throw new UnsupportedOperationException(); - } - - public String getRequestURI() { - throw new UnsupportedOperationException(); - } - - public StringBuffer getRequestURL() { - throw new UnsupportedOperationException(); - } - - public String getScheme() { - throw new UnsupportedOperationException(); - } - - public String getServerName() { - throw new UnsupportedOperationException(); - } - - public int getServerPort() { - throw new UnsupportedOperationException(); - } - - public String getServletPath() { - throw new UnsupportedOperationException(); - } - - public HttpSession getSession() { - throw new UnsupportedOperationException(); - } - - public HttpSession getSession(boolean arg0) { - throw new UnsupportedOperationException(); - } - - public Principal getUserPrincipal() { - throw new UnsupportedOperationException(); - } - - public boolean isRequestedSessionIdFromCookie() { - throw new UnsupportedOperationException(); - } - - public boolean isRequestedSessionIdFromUrl() { - throw new UnsupportedOperationException(); - } - - public boolean isRequestedSessionIdFromURL() { - throw new UnsupportedOperationException(); - } - - public boolean isRequestedSessionIdValid() { - throw new UnsupportedOperationException(); - } - - public boolean isSecure() { - throw new UnsupportedOperationException(); - } - - public boolean isUserInRole(String arg0) { - throw new UnsupportedOperationException(); - } - - public void removeAttribute(String arg0) { - throw new UnsupportedOperationException(); - } - - public void setAttribute(String arg0, Object arg1) { - throw new UnsupportedOperationException(); - } - - public void setCharacterEncoding(String arg0) { - throw new UnsupportedOperationException(); - } } private class MockServletConfig implements ServletConfig { @@ -427,7 +208,7 @@ RemoteServiceServlet rss = new RemoteServiceServlet(); - MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath(); rss.init(mockConfig); mockRequest.contextPath = "/MyModule"; @@ -455,7 +236,7 @@ RemoteServiceServlet rss = new RemoteServiceServlet(); - MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath(); rss.init(mockConfig); mockRequest.contextPath = "/foo"; @@ -498,7 +279,7 @@ RemoteServiceServlet rss = new RemoteServiceServlet(); - MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + MockHttpServletRequestContextPath mockRequest = new MockHttpServletRequestContextPath(); rss.init(mockConfig); mockRequest.contextPath = "/MyModule";
diff --git a/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTestServiceImpl.java index ba11a06..7c7e3d5 100644 --- a/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTestServiceImpl.java +++ b/user/test/com/google/gwt/user/server/rpc/RemoteServiceServletTestServiceImpl.java
@@ -15,9 +15,29 @@ */ package com.google.gwt.user.server.rpc; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + /** * TODO: document me. */ public class RemoteServiceServletTestServiceImpl extends RemoteServiceServletTestServiceImplBase { + /** + * Explicitly return a 404 for the "404" URL. + */ + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (req.getPathInfo() != null && req.getPathInfo().endsWith("404")) { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, + "Intentionally not found URL"); + return; + } + super.service(req, resp); + } + }