Author: knopp Date: Wed Jun 13 03:00:48 2007 New Revision: 546798 URL: http://svn.apache.org/viewvc?view=rev&rev=546798 Log: Ignore Ajax request while regular request for same page is processed
Added: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/IgnoreAjaxRequestException.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/basic/EmptyAjaxRequestTarget.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Session.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebRequestCycleProcessor.java incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebSession.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Session.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Session.java?view=diff&rev=546798&r1=546797&r2=546798 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Session.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Session.java Wed Jun 13 03:00:48 2007 @@ -34,6 +34,7 @@ import org.apache.wicket.feedback.FeedbackMessage; import org.apache.wicket.feedback.FeedbackMessages; import org.apache.wicket.feedback.IFeedbackMessageFilter; +import org.apache.wicket.protocol.http.IgnoreAjaxRequestException; import org.apache.wicket.request.ClientInfo; import org.apache.wicket.session.ISessionStore; import org.apache.wicket.util.lang.Objects; @@ -338,6 +339,15 @@ /** Application level meta data. */ private MetaDataEntry[] metaData; + /** + * We need to know both thread that keeps the pagemap lock and the RequestCycle + */ + private static class PageMapsUsedInRequestEntry + { + Thread thread; + RequestCycle requestCycle; + }; + private transient Map pageMapsUsedInRequest; /** True, if session has been invalidated */ @@ -618,6 +628,18 @@ } /** + * When a regular request on certain page with certain version is being + * processed, we don't allow ajax requests to same page and version. + * + * @param lockedRequestCycle + * @return whether current request is valid or sould be discarded + */ + protected boolean isCurrentRequestValid(RequestCycle lockedRequestCycle) + { + return true; + } + + /** * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT. * * Get the page for the given path. @@ -659,10 +681,20 @@ // later Duration timeout = Application.get().getRequestCycleSettings().getTimeout(); + PageMapsUsedInRequestEntry entry = (PageMapsUsedInRequestEntry)pageMapsUsedInRequest + .get(pageMap); + // Get page entry for id and version - Thread t = (Thread)pageMapsUsedInRequest.get(pageMap); + Thread t = entry != null ? entry.thread : null; while (t != null && t != Thread.currentThread()) { + if (isCurrentRequestValid(entry.requestCycle) == false) + { + // we need to ignore this request. That's because it is an ajax request + // while regular page request is being processed + throw new IgnoreAjaxRequestException(); + } + try { pageMapsUsedInRequest.wait(timeout.getMilliseconds()); @@ -671,7 +703,10 @@ { throw new WicketRuntimeException(ex); } - t = (Thread)pageMapsUsedInRequest.get(pageMap); + + entry = (PageMapsUsedInRequestEntry)pageMapsUsedInRequest.get(pageMap); + t = entry != null ? entry.thread : null; + if (t != null && t != Thread.currentThread() && (startTime + timeout.getMilliseconds()) < System.currentTimeMillis()) { @@ -683,7 +718,11 @@ + ", giving up trying to get the page for path: " + path); } } - pageMapsUsedInRequest.put(pageMap, Thread.currentThread()); + + PageMapsUsedInRequestEntry newEntry = new PageMapsUsedInRequestEntry(); + newEntry.thread = Thread.currentThread(); + newEntry.requestCycle = RequestCycle.get(); + pageMapsUsedInRequest.put(pageMap, newEntry); final String id = Strings.firstPathComponent(path, Component.PATH_SEPARATOR); Page page = pageMap.get(Integer.parseInt(id), versionNumber); if (page == null) @@ -1366,7 +1405,7 @@ while (it.hasNext()) { Entry entry = (Entry)it.next(); - if (entry.getValue() == t) + if (((PageMapsUsedInRequestEntry)entry.getValue()).thread == t) { it.remove(); } Added: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/IgnoreAjaxRequestException.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/IgnoreAjaxRequestException.java?view=auto&rev=546798 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/IgnoreAjaxRequestException.java (added) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/IgnoreAjaxRequestException.java Wed Jun 13 03:00:48 2007 @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.wicket.protocol.http; + +import org.apache.wicket.Session; + +/** + * This exeption is thrown in [EMAIL PROTECTED] Session} class when an Ajax requests attempts + * to get a lock on pagemap while a regular request is processing the same page. + * <p> + * @author Matej Knopp + */ +// TODO: Using an exception to control flow is not the nicest way +public class IgnoreAjaxRequestException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + +} Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebRequestCycleProcessor.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebRequestCycleProcessor.java?view=diff&rev=546798&r1=546797&r2=546798 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebRequestCycleProcessor.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebRequestCycleProcessor.java Wed Jun 13 03:00:48 2007 @@ -32,6 +32,7 @@ import org.apache.wicket.request.AbstractRequestCycleProcessor; import org.apache.wicket.request.IRequestCodingStrategy; import org.apache.wicket.request.RequestParameters; +import org.apache.wicket.request.target.basic.EmptyAjaxRequestTarget; import org.apache.wicket.util.string.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -133,7 +134,11 @@ } if (processRequest) { - target = resolveRenderedPage(requestCycle, requestParameters); + try { + target = resolveRenderedPage(requestCycle, requestParameters); + } catch (IgnoreAjaxRequestException e) { + target = EmptyAjaxRequestTarget.getInstance(); + } } else { Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebSession.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebSession.java?view=diff&rev=546798&r1=546797&r2=546798 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebSession.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/protocol/http/WebSession.java Wed Jun 13 03:00:48 2007 @@ -17,9 +17,11 @@ package org.apache.wicket.protocol.http; import org.apache.wicket.Application; +import org.apache.wicket.Component; import org.apache.wicket.Request; import org.apache.wicket.RequestCycle; import org.apache.wicket.Session; +import org.apache.wicket.util.string.Strings; /** * A session subclass for the HTTP protocol. @@ -56,5 +58,42 @@ public WebSession(final WebApplication application, Request request) { super(application, request); + } + + /** + * @see org.apache.wicket.Session#isCurrentRequestValid(org.apache.wicket.RequestCycle) + */ + protected boolean isCurrentRequestValid(RequestCycle lockedRequestCycle) + { + WebRequest lockedRequest = (WebRequest) lockedRequestCycle.getRequest(); + + // if the request that's holding the lock is ajax, we allow this request + if (lockedRequest.isAjax() == true) + { + return true; + } + + RequestCycle currentRequestCycle = RequestCycle.get(); + WebRequest currentRequest = (WebRequest) currentRequestCycle.getRequest(); + + if (currentRequest.isAjax() == false) + { + // if this request is not ajax, we allow it + return true; + } + + String lockedPageId = Strings.firstPathComponent(lockedRequest.getRequestParameters().getComponentPath(), Component.PATH_SEPARATOR); + String currentPageId = Strings.firstPathComponent(currentRequestCycle.getRequest().getRequestParameters().getComponentPath(), Component.PATH_SEPARATOR); + + int lockedVersion = lockedRequest.getRequestParameters().getVersionNumber(); + int currentVersion = currentRequest.getRequestParameters().getVersionNumber(); + + if (currentPageId.equals(lockedPageId) && currentVersion == lockedVersion) + { + // we don't allow tis request + return false; + } + + return true; } } Added: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/basic/EmptyAjaxRequestTarget.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/basic/EmptyAjaxRequestTarget.java?view=auto&rev=546798 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/basic/EmptyAjaxRequestTarget.java (added) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/request/target/basic/EmptyAjaxRequestTarget.java Wed Jun 13 03:00:48 2007 @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.wicket.request.target.basic; + +import org.apache.wicket.IRequestTarget; +import org.apache.wicket.RequestCycle; + +/** + * The empty AJAX request target does output an empty AJAX response. + * + * @author Matej Knopp + */ +public final class EmptyAjaxRequestTarget implements IRequestTarget +{ + /** immutable hashcode. */ + private static final int HASH = 17 * 1542323; + + /** singleton instance. */ + private static final EmptyAjaxRequestTarget instance = new EmptyAjaxRequestTarget(); + + /** + * Construct. + */ + private EmptyAjaxRequestTarget() + { + } + + /** + * Gets the singleton instance. + * + * @return the singleton instance + */ + public static final EmptyAjaxRequestTarget getInstance() + { + return instance; + } + + /** + * @see org.apache.wicket.IRequestTarget#respond(org.apache.wicket.RequestCycle) + */ + public void respond(RequestCycle requestCycle) + { + requestCycle.getResponse().write("<ajax-response></ajax-response>"); + } + + /** + * @see org.apache.wicket.IRequestTarget#detach(org.apache.wicket.RequestCycle) + */ + public void detach(RequestCycle requestCycle) + { + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) + { + if (obj instanceof EmptyAjaxRequestTarget) + { + return true; + } + return false; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() + { + return HASH; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() + { + return "EmptyAjaxRequestTarget"; + } +}