You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2015/06/27 09:11:30 UTC
[1/2] wicket git commit: WICKET-5929 renamed *AjaxResponse to
*PartialPageUpdate; moved all XML related encoding into XmlPartialPageUpdate
Repository: wicket
Updated Branches:
refs/heads/master e5f08f1b2 -> 470f2a286
WICKET-5929 renamed *AjaxResponse to *PartialPageUpdate; moved all XML related encoding into XmlPartialPageUpdate
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/7c40e4da
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/7c40e4da
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/7c40e4da
Branch: refs/heads/master
Commit: 7c40e4dafa75973bf99b34567d977f310a5f02d0
Parents: e5f08f1
Author: Sven Meier <sv...@apache.org>
Authored: Fri Jun 26 23:01:50 2015 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jun 27 09:03:04 2015 +0200
----------------------------------------------------------------------
.../wicket/ajax/AbstractAjaxResponse.java | 830 -------------------
.../apache/wicket/ajax/AjaxRequestHandler.java | 4 +-
.../apache/wicket/ajax/PartialPageUpdate.java | 786 ++++++++++++++++++
.../org/apache/wicket/ajax/XmlAjaxResponse.java | 233 ------
.../wicket/ajax/XmlPartialPageUpdate.java | 234 ++++++
.../filter/XmlCleaningResponseFilter.java | 4 +-
.../filter/XmlCleaningResponseFilterTest.java | 4 +-
.../ws/api/WebSocketRequestHandler.java | 27 +-
8 files changed, 1039 insertions(+), 1083 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java
deleted file mode 100644
index f949171..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * 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.ajax;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.Cookie;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.Page;
-import org.apache.wicket.markup.head.HeaderItem;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.IWrappedHeaderItem;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
-import org.apache.wicket.markup.head.OnEventHeaderItem;
-import org.apache.wicket.markup.head.OnLoadHeaderItem;
-import org.apache.wicket.markup.head.PriorityHeaderItem;
-import org.apache.wicket.markup.head.internal.HeaderResponse;
-import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
-import org.apache.wicket.markup.parser.filter.HtmlHeaderSectionHandler;
-import org.apache.wicket.markup.renderStrategy.AbstractHeaderRenderStrategy;
-import org.apache.wicket.markup.renderStrategy.IHeaderRenderStrategy;
-import org.apache.wicket.markup.repeater.AbstractRepeater;
-import org.apache.wicket.request.IRequestCycle;
-import org.apache.wicket.request.Response;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.apache.wicket.request.http.WebResponse;
-import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.lang.Classes;
-import org.apache.wicket.util.lang.Generics;
-import org.apache.wicket.util.string.AppendingStringBuffer;
-import org.apache.wicket.util.string.Strings;
-import org.apache.wicket.util.time.Time;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A POJO-like that collects the data for the Ajax response written to the client
- * and serializes it to specific String-based format (XML, JSON, ...).
- */
-public abstract class AbstractAjaxResponse
-{
- private static final Logger LOG = LoggerFactory.getLogger(AbstractAjaxResponse.class);
-
- /**
- * A list of scripts (JavaScript) which should be executed on the client side before the
- * components' replacement
- */
- protected final List<CharSequence> prependJavaScripts = Generics.newArrayList();
-
- /**
- * A list of scripts (JavaScript) which should be executed on the client side after the
- * components' replacement
- */
- protected final List<CharSequence> appendJavaScripts = Generics.newArrayList();
-
- /**
- * A list of scripts (JavaScript) which should be executed on the client side after the
- * components' replacement.
- * Executed immediately after the replacement of the components, and before appendJavaScripts
- */
- protected final List<CharSequence> domReadyJavaScripts = Generics.newArrayList();
-
- /**
- * The component instances that will be rendered/replaced.
- */
- protected final Map<String, Component> markupIdToComponent = new LinkedHashMap<String, Component>();
-
- /**
- * A flag that indicates that components cannot be added to AjaxRequestTarget anymore.
- * See https://issues.apache.org/jira/browse/WICKET-3564
- */
- protected transient boolean componentsFrozen;
-
- /**
- * Create a response for component body and javascript that will escape output to make it safe
- * to use inside a CDATA block
- */
- protected final AjaxResponse encodingBodyResponse;
-
- /**
- * Response for header contribution that will escape output to make it safe to use inside a
- * CDATA block
- */
- protected final AjaxResponse encodingHeaderResponse;
-
- protected HtmlHeaderContainer header = null;
-
- // whether a header contribution is being rendered
- private boolean headerRendering = false;
-
- private IHeaderResponse headerResponse;
-
- /**
- * The page which components are being updated.
- */
- private final Page page;
-
- /**
- * Constructor.
- *
- * @param page
- * the page which components are being updated.
- */
- public AbstractAjaxResponse(final Page page)
- {
- this.page = page;
-
- WebResponse response = (WebResponse) page.getResponse();
- encodingBodyResponse = new AjaxResponse(response);
- encodingHeaderResponse = new AjaxResponse(response);
- }
-
- /**
- * Serializes this object to the response.
- *
- * @param response
- * the response to write to
- * @param encoding
- * the encoding for the response
- */
- public void writeTo(final Response response, final String encoding)
- {
- writeHeader(response, encoding);
-
- // invoke onbeforerespond event on listeners
- fireOnBeforeRespondListeners();
-
- // process added components
- writeComponents(response, encoding);
-
- fireOnAfterRespondListeners(response);
-
- // queue up prepend javascripts. unlike other steps these are executed out of order so that
- // components can contribute them from inside their onbeforerender methods.
- writePriorityEvaluations(response, prependJavaScripts);
-
- // execute the dom ready javascripts as first javascripts
- // after component replacement
- List<CharSequence> evaluationScripts = new ArrayList<>();
- evaluationScripts.addAll(domReadyJavaScripts);
- evaluationScripts.addAll(appendJavaScripts);
- writeNormalEvaluations(response, evaluationScripts);
-
- writeFooter(response, encoding);
- }
-
- protected abstract void fireOnAfterRespondListeners(Response response);
-
- protected abstract void fireOnBeforeRespondListeners();
-
- /**
- * @param response
- * the response to write to
- * @param encoding
- * the encoding for the response
- */
- protected abstract void writeFooter(Response response, String encoding);
-
- /**
- *
- * @param response
- * the response to write to
- * @param js
- * the JavaScript to evaluate
- */
- protected abstract void writePriorityEvaluations(Response response, Collection<CharSequence> js);
-
- /**
- *
- * @param response
- * the response to write to
- * @param js
- * the JavaScript to evaluate
- */
- protected abstract void writeNormalEvaluations(Response response, Collection<CharSequence> js);
-
- /**
- * Processes components added to the target. This involves attaching components, rendering
- * markup into a client side xml envelope, and detaching them
- *
- * @param response
- * the response to write to
- * @param encoding
- * the encoding for the response
- */
- private void writeComponents(Response response, String encoding)
- {
- componentsFrozen = true;
-
- // process component markup
- for (Map.Entry<String, Component> stringComponentEntry : markupIdToComponent.entrySet())
- {
- final Component component = stringComponentEntry.getValue();
-
- if (!containsAncestorFor(component))
- {
- writeComponent(response, component.getAjaxRegionMarkupId(), component, encoding);
- }
- }
-
- if (header != null)
- {
- // some header responses buffer all calls to render*** until close is called.
- // when they are closed, they do something (i.e. aggregate all JS resource urls to a
- // single url), and then "flush" (by writing to the real response) before closing.
- // to support this, we need to allow header contributions to be written in the close
- // tag, which we do here:
- headerRendering = true;
- // save old response, set new
- Response oldResponse = RequestCycle.get().setResponse(encodingHeaderResponse);
- encodingHeaderResponse.reset();
-
- // now, close the response (which may render things)
- header.getHeaderResponse().close();
-
- // revert to old response
- RequestCycle.get().setResponse(oldResponse);
-
- // write the XML tags and we're done
- writeHeaderContribution(response);
- headerRendering = false;
- }
- }
-
- /**
- * Writes a single component
- *
- * @param response
- * the response to write to
- * @param markupId
- * the markup id to use for the component replacement
- * @param component
- * the component which markup will be used as replacement
- * @param encoding
- * the encoding for the response
- */
- protected abstract void writeComponent(Response response, String markupId, Component component, String encoding);
-
- /**
- * Writes the head part of the response.
- * For example XML preamble
- *
- * @param response
- * the response to write to
- * @param encoding
- * the encoding for the response
- */
- protected abstract void writeHeader(Response response, String encoding);
-
- /**
- * Writes header contribution (<link/> or <script/>) to the response.
- *
- * @param response
- * the response to write to
- */
- protected abstract void writeHeaderContribution(Response response);
-
- @Override
- public boolean equals(Object o)
- {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- AbstractAjaxResponse that = (AbstractAjaxResponse) o;
-
- if (!appendJavaScripts.equals(that.appendJavaScripts)) return false;
- if (!domReadyJavaScripts.equals(that.domReadyJavaScripts)) return false;
- return prependJavaScripts.equals(that.prependJavaScripts);
- }
-
- @Override
- public int hashCode()
- {
- int result = prependJavaScripts.hashCode();
- result = 31 * result + appendJavaScripts.hashCode();
- result = 31 * result + domReadyJavaScripts.hashCode();
- return result;
- }
-
- /**
- * Adds script to the ones which are executed after the component replacement.
- *
- * @param javascript
- * the javascript to execute
- */
- public final void appendJavaScript(final CharSequence javascript)
- {
- Args.notNull(javascript, "javascript");
-
- appendJavaScripts.add(javascript);
- }
-
- /**
- * Adds script to the ones which are executed before the component replacement.
- *
- * @param javascript
- * the javascript to execute
- */
- public final void prependJavaScript(CharSequence javascript)
- {
- Args.notNull(javascript, "javascript");
-
- prependJavaScripts.add(javascript);
- }
-
- /**
- * Adds a component to be updated at the client side with its current markup
- *
- * @param component
- * the component to update
- * @param markupId
- * the markup id to use to find the component in the page's markup
- * @throws IllegalArgumentException
- * thrown when a Page or an AbstractRepeater is added
- * @throws IllegalStateException
- * thrown when components no more can be added for replacement.
- */
- public final void add(final Component component, final String markupId)
- throws IllegalArgumentException, IllegalStateException
- {
- Args.notEmpty(markupId, "markupId");
- Args.notNull(component, "component");
-
- if (component instanceof Page)
- {
- if (component != page)
- {
- throw new IllegalArgumentException("component cannot be a page");
- }
- }
- else if (component instanceof AbstractRepeater)
- {
- throw new IllegalArgumentException(
- "Component " +
- component.getClass().getName() +
- " has been added to the target. This component is a repeater and cannot be repainted via ajax directly. " +
- "Instead add its parent or another markup container higher in the hierarchy.");
- }
-
- assertComponentsNotFrozen();
-
- component.setMarkupId(markupId);
- markupIdToComponent.put(markupId, component);
- }
-
- /**
- * @return a read-only collection of all components which have been added for replacement so far.
- */
- public final Collection<? extends Component> getComponents()
- {
- return Collections.unmodifiableCollection(markupIdToComponent.values());
- }
-
- /**
- * Detaches the page if at least one of its components was updated.
- *
- * @param requestCycle
- * the current request cycle
- */
- public void detach(IRequestCycle requestCycle)
- {
- Iterator<Component> iterator = markupIdToComponent.values().iterator();
- while (iterator.hasNext())
- {
- final Component component = iterator.next();
- final Page parentPage = component.findParent(Page.class);
- if (parentPage != null)
- {
- parentPage.detach();
- break;
- }
- }
- }
-
- /**
- * Checks if the target contains an ancestor for the given component
- *
- * @param component
- * the component which ancestors should be checked.
- * @return <code>true</code> if target contains an ancestor for the given component
- */
- protected boolean containsAncestorFor(Component component)
- {
- Component cursor = component.getParent();
- while (cursor != null)
- {
- if (markupIdToComponent.containsValue(cursor))
- {
- return true;
- }
- cursor = cursor.getParent();
- }
- return false;
- }
-
- /**
- * @return {@code true} if the page has been added for replacement
- */
- boolean containsPage()
- {
- return markupIdToComponent.values().contains(page);
- }
-
- /**
- * Gets or creates an IHeaderResponse instance to use for the header contributions.
- *
- * @return IHeaderResponse instance to use for the header contributions.
- */
- public IHeaderResponse getHeaderResponse()
- {
- if (headerResponse == null)
- {
- // we don't need to decorate the header response here because this is called from
- // within AjaxHtmlHeaderContainer, which decorates the response
- headerResponse = new AjaxHeaderResponse();
- }
- return headerResponse;
- }
-
- /**
- * @param response
- * the response to write to
- * @param component
- * to component which will contribute to the header
- */
- protected void writeHeaderContribution(final Response response, final Component component)
- {
- headerRendering = true;
-
- // create the htmlheadercontainer if needed
- if (header == null)
- {
- header = new AjaxHtmlHeaderContainer(this);
- final Page parentPage = component.getPage();
- parentPage.addOrReplace(header);
- }
-
- RequestCycle requestCycle = component.getRequestCycle();
-
- // save old response, set new
- Response oldResponse = requestCycle.setResponse(encodingHeaderResponse);
-
- try {
- encodingHeaderResponse.reset();
-
- IHeaderRenderStrategy strategy = AbstractHeaderRenderStrategy.get();
-
- strategy.renderHeader(header, null, component);
- } finally {
- // revert to old response
- requestCycle.setResponse(oldResponse);
- }
-
- writeHeaderContribution(response);
-
- headerRendering = false;
- }
-
- /**
- * Sets the Content-Type header to indicate the type of the Ajax response.
- *
- * @param response
- * the current we response
- * @param encoding
- * the encoding to use
- */
- protected abstract void setContentType(WebResponse response, String encoding);
-
-
- /**
- * Header container component for ajax header contributions
- *
- * @author Matej Knopp
- */
- private static class AjaxHtmlHeaderContainer extends HtmlHeaderContainer
- {
- private static final long serialVersionUID = 1L;
-
- private transient AbstractAjaxResponse ajaxResponse;
-
- /**
- * Constructor.
- *
- * @param ajaxResponse
- * the object that keeps the data for the Ajax response
- */
- public AjaxHtmlHeaderContainer(final AbstractAjaxResponse ajaxResponse)
- {
- super(HtmlHeaderSectionHandler.HEADER_ID);
- this.ajaxResponse = ajaxResponse;
- }
-
- /**
- *
- * @see org.apache.wicket.markup.html.internal.HtmlHeaderContainer#newHeaderResponse()
- */
- @Override
- protected IHeaderResponse newHeaderResponse()
- {
- if (ajaxResponse != null)
- {
- return ajaxResponse.getHeaderResponse();
- }
-
- return super.newHeaderResponse();
- }
-
- @Override
- protected void onDetach()
- {
- super.onDetach();
- ajaxResponse = null;
- }
- }
-
- /**
- * Header response for an ajax request.
- *
- * @author Matej Knopp
- */
- private class AjaxHeaderResponse extends HeaderResponse
- {
- @Override
- public void render(HeaderItem item)
- {
- PriorityHeaderItem priorityHeaderItem = null;
- while (item instanceof IWrappedHeaderItem)
- {
- if (item instanceof PriorityHeaderItem)
- {
- priorityHeaderItem = (PriorityHeaderItem) item;
- }
- item = ((IWrappedHeaderItem) item).getWrapped();
- }
-
- if (item instanceof OnLoadHeaderItem)
- {
- if (!wasItemRendered(item))
- {
- AbstractAjaxResponse.this.appendJavaScript(((OnLoadHeaderItem) item).getJavaScript());
- markItemRendered(item);
- }
- }
- else if (item instanceof OnEventHeaderItem)
- {
- if (!wasItemRendered(item))
- {
- AbstractAjaxResponse.this.appendJavaScript(((OnEventHeaderItem) item).getCompleteJavaScript());
- markItemRendered(item);
- }
- }
- else if (item instanceof OnDomReadyHeaderItem)
- {
- if (!wasItemRendered(item))
- {
- if (priorityHeaderItem != null)
- {
- AbstractAjaxResponse.this.domReadyJavaScripts.add(0, ((OnDomReadyHeaderItem)item).getJavaScript());
- }
- else
- {
- AbstractAjaxResponse.this.domReadyJavaScripts.add(((OnDomReadyHeaderItem)item).getJavaScript());
- }
- markItemRendered(item);
- }
- }
- else if (headerRendering)
- {
- super.render(item);
- }
- else
- {
- LOG.debug("Only methods that can be called on IHeaderResponse outside renderHead() are #render(OnLoadHeaderItem) and #render(OnDomReadyHeaderItem)");
- }
- }
-
- @Override
- protected Response getRealResponse()
- {
- return RequestCycle.get().getResponse();
- }
- }
-
- /**
- * Response that uses an encoder to encode its contents
- *
- * @author Igor Vaynberg (ivaynberg)
- */
- protected static final class AjaxResponse extends WebResponse
- {
- private final AppendingStringBuffer buffer = new AppendingStringBuffer(256);
-
- private boolean escaped = false;
-
- private final WebResponse originalResponse;
-
- /**
- * Constructor.
- *
- * @param originalResponse
- * the original request cycle response
- */
- private AjaxResponse(WebResponse originalResponse)
- {
- this.originalResponse = originalResponse;
- }
-
- /**
- * @see org.apache.wicket.request.Response#encodeURL(CharSequence)
- */
- @Override
- public String encodeURL(CharSequence url)
- {
- return originalResponse.encodeURL(url);
- }
-
- /**
- * @return contents of the response
- */
- public CharSequence getContents()
- {
- return buffer;
- }
-
- /**
- * @return true if any escaping has been performed, false otherwise
- */
- public boolean isContentsEncoded()
- {
- return escaped;
- }
-
- /**
- * @see org.apache.wicket.request.Response#write(CharSequence)
- */
- @Override
- public void write(CharSequence cs)
- {
- String string = cs.toString();
- if (needsEncoding(string))
- {
- string = encode(string);
- escaped = true;
- buffer.append(string);
- }
- else
- {
- buffer.append(cs);
- }
- }
-
- /**
- * Resets the response to a clean state so it can be reused to save on garbage.
- */
- @Override
- public void reset()
- {
- buffer.clear();
- escaped = false;
- }
-
- @Override
- public void write(byte[] array)
- {
- throw new UnsupportedOperationException("Cannot write binary data.");
- }
-
- @Override
- public void write(byte[] array, int offset, int length)
- {
- throw new UnsupportedOperationException("Cannot write binary data.");
- }
-
- @Override
- public Object getContainerResponse()
- {
- return originalResponse.getContainerResponse();
- }
-
- @Override
- public void addCookie(Cookie cookie)
- {
- originalResponse.addCookie(cookie);
- }
-
- @Override
- public void clearCookie(Cookie cookie)
- {
- originalResponse.clearCookie(cookie);
- }
-
- @Override
- public void setHeader(String name, String value)
- {
- originalResponse.setHeader(name, value);
- }
-
- @Override
- public void addHeader(String name, String value)
- {
- originalResponse.addHeader(name, value);
- }
-
- @Override
- public void setDateHeader(String name, Time date)
- {
- originalResponse.setDateHeader(name, date);
- }
-
- @Override
- public void setContentLength(long length)
- {
- originalResponse.setContentLength(length);
- }
-
- @Override
- public void setContentType(String mimeType)
- {
- originalResponse.setContentType(mimeType);
- }
-
- @Override
- public void setStatus(int sc)
- {
- originalResponse.setStatus(sc);
- }
-
- @Override
- public void sendError(int sc, String msg)
- {
- originalResponse.sendError(sc, msg);
- }
-
- @Override
- public String encodeRedirectURL(CharSequence url)
- {
- return originalResponse.encodeRedirectURL(url);
- }
-
- @Override
- public void sendRedirect(String url)
- {
- originalResponse.sendRedirect(url);
- }
-
- @Override
- public boolean isRedirect()
- {
- return originalResponse.isRedirect();
- }
-
- @Override
- public void flush()
- {
- originalResponse.flush();
- }
- }
-
- /**
- * Encodes a string so it is safe to use inside CDATA blocks
- *
- * @param str
- * the string to encode.
- * @return encoded string
- */
- static String encode(CharSequence str)
- {
- if (str == null)
- {
- return null;
- }
-
- // split each CDATA end sequence
- return Strings.replaceAll(str, "]]>", "]]]]><![CDATA[>").toString();
- }
-
- /**
- *
- * @param str
- * the string to check
- * @return {@code true} if string needs to be encoded, {@code false} otherwise
- */
- static boolean needsEncoding(CharSequence str)
- {
- /*
- * TODO Post 1.2: Ajax: we can improve this by keeping a buffer of at least 3 characters and
- * checking that buffer so that we can narrow down escaping occurring only for ']]>'
- * sequence, or at least for ]] if ] is the last char in this buffer.
- *
- * but this improvement will only work if we write first and encode later instead of working
- * on fragments sent to write
- */
- return Strings.indexOf(str, ']') >= 0;
- }
-
- private void assertComponentsNotFrozen()
- {
- assertNotFrozen(componentsFrozen, Component.class);
- }
-
- private void assertNotFrozen(boolean frozen, Class<?> clazz)
- {
- if (frozen)
- {
- throw new IllegalStateException(Classes.simpleName(clazz) + "s can no " +
- " longer be added");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
index cbb9770..439319d 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
@@ -84,7 +84,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
* A POJO-like that collects the data for the Ajax response written to the client and serializes
* it to specific String-based format (XML, JSON, ...).
*/
- private final AbstractAjaxResponse responseObject;
+ private final PartialPageUpdate responseObject;
/** a list of listeners */
private List<AjaxRequestTarget.IListener> listeners = null;
@@ -111,7 +111,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
{
this.page = Args.notNull(page, "page");
- responseObject = new XmlAjaxResponse(page)
+ responseObject = new XmlPartialPageUpdate(page)
{
/**
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
new file mode 100644
index 0000000..5970f38
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
@@ -0,0 +1,786 @@
+/*
+ * 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.ajax;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.head.HeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.IWrappedHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.head.OnEventHeaderItem;
+import org.apache.wicket.markup.head.OnLoadHeaderItem;
+import org.apache.wicket.markup.head.PriorityHeaderItem;
+import org.apache.wicket.markup.head.internal.HeaderResponse;
+import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
+import org.apache.wicket.markup.parser.filter.HtmlHeaderSectionHandler;
+import org.apache.wicket.markup.renderStrategy.AbstractHeaderRenderStrategy;
+import org.apache.wicket.markup.renderStrategy.IHeaderRenderStrategy;
+import org.apache.wicket.markup.repeater.AbstractRepeater;
+import org.apache.wicket.request.IRequestCycle;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Classes;
+import org.apache.wicket.util.lang.Generics;
+import org.apache.wicket.util.string.AppendingStringBuffer;
+import org.apache.wicket.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A partial update of a page that collects components and header contributions to be written to the client in a specific
+ * String-based format (XML, JSON, * ...).
+ * <p>
+ * The elements of such response are:
+ * <ul>
+ * <li>priority-evaluate - an item of the prepend JavaScripts</li>
+ * <li>component - the markup of the updated component</li>
+ * <li>evaluate - an item of the onDomReady and append JavaScripts</li>
+ * <li>header-contribution - all HeaderItems which have been contributed in
+ * components' and their behaviors' #renderHead(Component, IHeaderResponse)</li>
+ * </ul>
+ */
+public abstract class PartialPageUpdate
+{
+ private static final Logger LOG = LoggerFactory.getLogger(PartialPageUpdate.class);
+
+ /**
+ * A list of scripts (JavaScript) which should be executed on the client side before the
+ * components' replacement
+ */
+ protected final List<CharSequence> prependJavaScripts = Generics.newArrayList();
+
+ /**
+ * A list of scripts (JavaScript) which should be executed on the client side after the
+ * components' replacement
+ */
+ protected final List<CharSequence> appendJavaScripts = Generics.newArrayList();
+
+ /**
+ * A list of scripts (JavaScript) which should be executed on the client side after the
+ * components' replacement.
+ * Executed immediately after the replacement of the components, and before appendJavaScripts
+ */
+ protected final List<CharSequence> domReadyJavaScripts = Generics.newArrayList();
+
+ /**
+ * The component instances that will be rendered/replaced.
+ */
+ protected final Map<String, Component> markupIdToComponent = new LinkedHashMap<String, Component>();
+
+ /**
+ * A flag that indicates that components cannot be added anymore.
+ * See https://issues.apache.org/jira/browse/WICKET-3564
+ *
+ * @see #add(Component, String)
+ */
+ protected transient boolean componentsFrozen;
+
+ /**
+ * Create a response for component body and javascript that will escape output to make it safe
+ * to use inside a CDATA block
+ */
+ protected final ResponseWrapper encodingBodyResponse;
+
+ /**
+ * Response for header contribution that will escape output to make it safe to use inside a
+ * CDATA block
+ */
+ protected final ResponseWrapper encodingHeaderResponse;
+
+ protected HtmlHeaderContainer header = null;
+
+ // whether a header contribution is being rendered
+ private boolean headerRendering = false;
+
+ private IHeaderResponse headerResponse;
+
+ /**
+ * The page which components are being updated.
+ */
+ private final Page page;
+
+ /**
+ * Constructor.
+ *
+ * @param page
+ * the page which components are being updated.
+ */
+ public PartialPageUpdate(final Page page)
+ {
+ this.page = page;
+
+ WebResponse response = (WebResponse) page.getResponse();
+ encodingBodyResponse = new ResponseWrapper(response);
+ encodingHeaderResponse = new ResponseWrapper(response);
+ }
+
+ /**
+ * Serializes this object to the response.
+ *
+ * @param response
+ * the response to write to
+ * @param encoding
+ * the encoding for the response
+ */
+ public void writeTo(final Response response, final String encoding)
+ {
+ writeHeader(response, encoding);
+
+ // invoke onbeforerespond event on listeners
+ fireOnBeforeRespondListeners();
+
+ // process added components
+ writeComponents(response, encoding);
+
+ fireOnAfterRespondListeners(response);
+
+ // queue up prepend javascripts. unlike other steps these are executed out of order so that
+ // components can contribute them from inside their onbeforerender methods.
+ writePriorityEvaluations(response, prependJavaScripts);
+
+ // execute the dom ready javascripts as first javascripts
+ // after component replacement
+ List<CharSequence> evaluationScripts = new ArrayList<>();
+ evaluationScripts.addAll(domReadyJavaScripts);
+ evaluationScripts.addAll(appendJavaScripts);
+ writeNormalEvaluations(response, evaluationScripts);
+
+ writeFooter(response, encoding);
+ }
+
+ protected abstract void fireOnAfterRespondListeners(Response response);
+
+ protected abstract void fireOnBeforeRespondListeners();
+
+ /**
+ * @param response
+ * the response to write to
+ * @param encoding
+ * the encoding for the response
+ */
+ protected abstract void writeFooter(Response response, String encoding);
+
+ /**
+ *
+ * @param response
+ * the response to write to
+ * @param js
+ * the JavaScript to evaluate
+ */
+ protected abstract void writePriorityEvaluations(Response response, Collection<CharSequence> js);
+
+ /**
+ *
+ * @param response
+ * the response to write to
+ * @param js
+ * the JavaScript to evaluate
+ */
+ protected abstract void writeNormalEvaluations(Response response, Collection<CharSequence> js);
+
+ /**
+ * Processes components added to the target. This involves attaching components, rendering
+ * markup into a client side xml envelope, and detaching them
+ *
+ * @param response
+ * the response to write to
+ * @param encoding
+ * the encoding for the response
+ */
+ private void writeComponents(Response response, String encoding)
+ {
+ componentsFrozen = true;
+
+ // process component markup
+ for (Map.Entry<String, Component> stringComponentEntry : markupIdToComponent.entrySet())
+ {
+ final Component component = stringComponentEntry.getValue();
+
+ if (!containsAncestorFor(component))
+ {
+ writeComponent(response, component.getAjaxRegionMarkupId(), component, encoding);
+ }
+ }
+
+ if (header != null)
+ {
+ // some header responses buffer all calls to render*** until close is called.
+ // when they are closed, they do something (i.e. aggregate all JS resource urls to a
+ // single url), and then "flush" (by writing to the real response) before closing.
+ // to support this, we need to allow header contributions to be written in the close
+ // tag, which we do here:
+ headerRendering = true;
+ // save old response, set new
+ Response oldResponse = RequestCycle.get().setResponse(encodingHeaderResponse);
+ encodingHeaderResponse.reset();
+
+ // now, close the response (which may render things)
+ header.getHeaderResponse().close();
+
+ // revert to old response
+ RequestCycle.get().setResponse(oldResponse);
+
+ // write the XML tags and we're done
+ writeHeaderContribution(response);
+ headerRendering = false;
+ }
+ }
+
+ /**
+ * Writes a single component
+ *
+ * @param response
+ * the response to write to
+ * @param markupId
+ * the markup id to use for the component replacement
+ * @param component
+ * the component which markup will be used as replacement
+ * @param encoding
+ * the encoding for the response
+ */
+ protected abstract void writeComponent(Response response, String markupId, Component component, String encoding);
+
+ /**
+ * Writes the head part of the response.
+ * For example XML preamble
+ *
+ * @param response
+ * the response to write to
+ * @param encoding
+ * the encoding for the response
+ */
+ protected abstract void writeHeader(Response response, String encoding);
+
+ /**
+ * Writes header contribution (<link/> or <script/>) to the response.
+ *
+ * @param response
+ * the response to write to
+ */
+ protected abstract void writeHeaderContribution(Response response);
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PartialPageUpdate that = (PartialPageUpdate) o;
+
+ if (!appendJavaScripts.equals(that.appendJavaScripts)) return false;
+ if (!domReadyJavaScripts.equals(that.domReadyJavaScripts)) return false;
+ return prependJavaScripts.equals(that.prependJavaScripts);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = prependJavaScripts.hashCode();
+ result = 31 * result + appendJavaScripts.hashCode();
+ result = 31 * result + domReadyJavaScripts.hashCode();
+ return result;
+ }
+
+ /**
+ * Adds script to the ones which are executed after the component replacement.
+ *
+ * @param javascript
+ * the javascript to execute
+ */
+ public final void appendJavaScript(final CharSequence javascript)
+ {
+ Args.notNull(javascript, "javascript");
+
+ appendJavaScripts.add(javascript);
+ }
+
+ /**
+ * Adds script to the ones which are executed before the component replacement.
+ *
+ * @param javascript
+ * the javascript to execute
+ */
+ public final void prependJavaScript(CharSequence javascript)
+ {
+ Args.notNull(javascript, "javascript");
+
+ prependJavaScripts.add(javascript);
+ }
+
+ /**
+ * Adds a component to be updated at the client side with its current markup
+ *
+ * @param component
+ * the component to update
+ * @param markupId
+ * the markup id to use to find the component in the page's markup
+ * @throws IllegalArgumentException
+ * thrown when a Page or an AbstractRepeater is added
+ * @throws IllegalStateException
+ * thrown when components no more can be added for replacement.
+ */
+ public final void add(final Component component, final String markupId)
+ throws IllegalArgumentException, IllegalStateException
+ {
+ Args.notEmpty(markupId, "markupId");
+ Args.notNull(component, "component");
+
+ if (component instanceof Page)
+ {
+ if (component != page)
+ {
+ throw new IllegalArgumentException("component cannot be a page");
+ }
+ }
+ else if (component instanceof AbstractRepeater)
+ {
+ throw new IllegalArgumentException(
+ "Component " +
+ component.getClass().getName() +
+ " has been added to a partial page update. This component is a repeater and cannot be repainted directly. " +
+ "Instead add its parent or another markup container higher in the hierarchy.");
+ }
+
+ assertComponentsNotFrozen();
+
+ component.setMarkupId(markupId);
+ markupIdToComponent.put(markupId, component);
+ }
+
+ /**
+ * @return a read-only collection of all components which have been added for replacement so far.
+ */
+ public final Collection<? extends Component> getComponents()
+ {
+ return Collections.unmodifiableCollection(markupIdToComponent.values());
+ }
+
+ /**
+ * Detaches the page if at least one of its components was updated.
+ *
+ * @param requestCycle
+ * the current request cycle
+ */
+ public void detach(IRequestCycle requestCycle)
+ {
+ Iterator<Component> iterator = markupIdToComponent.values().iterator();
+ while (iterator.hasNext())
+ {
+ final Component component = iterator.next();
+ final Page parentPage = component.findParent(Page.class);
+ if (parentPage != null)
+ {
+ parentPage.detach();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Checks if the target contains an ancestor for the given component
+ *
+ * @param component
+ * the component which ancestors should be checked.
+ * @return <code>true</code> if target contains an ancestor for the given component
+ */
+ protected boolean containsAncestorFor(Component component)
+ {
+ Component cursor = component.getParent();
+ while (cursor != null)
+ {
+ if (markupIdToComponent.containsValue(cursor))
+ {
+ return true;
+ }
+ cursor = cursor.getParent();
+ }
+ return false;
+ }
+
+ /**
+ * @return {@code true} if the page has been added for replacement
+ */
+ boolean containsPage()
+ {
+ return markupIdToComponent.values().contains(page);
+ }
+
+ /**
+ * Gets or creates an IHeaderResponse instance to use for the header contributions.
+ *
+ * @return IHeaderResponse instance to use for the header contributions.
+ */
+ public IHeaderResponse getHeaderResponse()
+ {
+ if (headerResponse == null)
+ {
+ // we don't need to decorate the header response here because this is called from
+ // within PartialHtmlHeaderContainer, which decorates the response
+ headerResponse = new PartialHeaderResponse();
+ }
+ return headerResponse;
+ }
+
+ /**
+ * @param response
+ * the response to write to
+ * @param component
+ * to component which will contribute to the header
+ */
+ protected void writeHeaderContribution(final Response response, final Component component)
+ {
+ headerRendering = true;
+
+ // create the htmlheadercontainer if needed
+ if (header == null)
+ {
+ header = new PartialHtmlHeaderContainer(this);
+ final Page parentPage = component.getPage();
+ parentPage.addOrReplace(header);
+ }
+
+ RequestCycle requestCycle = component.getRequestCycle();
+
+ // save old response, set new
+ Response oldResponse = requestCycle.setResponse(encodingHeaderResponse);
+
+ try {
+ encodingHeaderResponse.reset();
+
+ IHeaderRenderStrategy strategy = AbstractHeaderRenderStrategy.get();
+
+ strategy.renderHeader(header, null, component);
+ } finally {
+ // revert to old response
+ requestCycle.setResponse(oldResponse);
+ }
+
+ writeHeaderContribution(response);
+
+ headerRendering = false;
+ }
+
+ /**
+ * Sets the Content-Type header to indicate the type of the response.
+ *
+ * @param response
+ * the current we response
+ * @param encoding
+ * the encoding to use
+ */
+ protected abstract void setContentType(WebResponse response, String encoding);
+
+
+ /**
+ * Header container component partial page updates.
+ *
+ * @author Matej Knopp
+ */
+ private static class PartialHtmlHeaderContainer extends HtmlHeaderContainer
+ {
+ private static final long serialVersionUID = 1L;
+
+ private transient PartialPageUpdate update;
+
+ /**
+ * Constructor.
+ *
+ * @param update
+ * the partial page update
+ */
+ public PartialHtmlHeaderContainer(final PartialPageUpdate update)
+ {
+ super(HtmlHeaderSectionHandler.HEADER_ID);
+ this.update = update;
+ }
+
+ /**
+ *
+ * @see org.apache.wicket.markup.html.internal.HtmlHeaderContainer#newHeaderResponse()
+ */
+ @Override
+ protected IHeaderResponse newHeaderResponse()
+ {
+ if (update != null)
+ {
+ return update.getHeaderResponse();
+ }
+
+ return super.newHeaderResponse();
+ }
+
+ @Override
+ protected void onDetach()
+ {
+ super.onDetach();
+ update = null;
+ }
+ }
+
+ /**
+ * Header response for partial updates.
+ *
+ * @author Matej Knopp
+ */
+ private class PartialHeaderResponse extends HeaderResponse
+ {
+ @Override
+ public void render(HeaderItem item)
+ {
+ PriorityHeaderItem priorityHeaderItem = null;
+ while (item instanceof IWrappedHeaderItem)
+ {
+ if (item instanceof PriorityHeaderItem)
+ {
+ priorityHeaderItem = (PriorityHeaderItem) item;
+ }
+ item = ((IWrappedHeaderItem) item).getWrapped();
+ }
+
+ if (item instanceof OnLoadHeaderItem)
+ {
+ if (!wasItemRendered(item))
+ {
+ PartialPageUpdate.this.appendJavaScript(((OnLoadHeaderItem) item).getJavaScript());
+ markItemRendered(item);
+ }
+ }
+ else if (item instanceof OnEventHeaderItem)
+ {
+ if (!wasItemRendered(item))
+ {
+ PartialPageUpdate.this.appendJavaScript(((OnEventHeaderItem) item).getCompleteJavaScript());
+ markItemRendered(item);
+ }
+ }
+ else if (item instanceof OnDomReadyHeaderItem)
+ {
+ if (!wasItemRendered(item))
+ {
+ if (priorityHeaderItem != null)
+ {
+ PartialPageUpdate.this.domReadyJavaScripts.add(0, ((OnDomReadyHeaderItem)item).getJavaScript());
+ }
+ else
+ {
+ PartialPageUpdate.this.domReadyJavaScripts.add(((OnDomReadyHeaderItem)item).getJavaScript());
+ }
+ markItemRendered(item);
+ }
+ }
+ else if (headerRendering)
+ {
+ super.render(item);
+ }
+ else
+ {
+ LOG.debug("Only methods that can be called on IHeaderResponse outside renderHead() are #render(OnLoadHeaderItem) and #render(OnDomReadyHeaderItem)");
+ }
+ }
+
+ @Override
+ protected Response getRealResponse()
+ {
+ return RequestCycle.get().getResponse();
+ }
+ }
+
+ /**
+ * Wrapper of a response.
+ *
+ * @author Igor Vaynberg (ivaynberg)
+ * @author Sven Meier (svenmeier)
+ *
+ * @see ResponseWrapper#getContents()
+ * @see ResponseWrapper#reset()
+ */
+ protected static final class ResponseWrapper extends WebResponse
+ {
+ private final AppendingStringBuffer buffer = new AppendingStringBuffer(256);
+
+ private final WebResponse originalResponse;
+
+ /**
+ * Constructor.
+ *
+ * @param originalResponse
+ * the original request cycle response
+ */
+ private ResponseWrapper(WebResponse originalResponse)
+ {
+ this.originalResponse = originalResponse;
+ }
+
+ /**
+ * @see org.apache.wicket.request.Response#encodeURL(CharSequence)
+ */
+ @Override
+ public String encodeURL(CharSequence url)
+ {
+ return originalResponse.encodeURL(url);
+ }
+
+ /**
+ * @return contents of the response
+ */
+ public CharSequence getContents()
+ {
+ return buffer;
+ }
+
+ /**
+ * @see org.apache.wicket.request.Response#write(CharSequence)
+ */
+ @Override
+ public void write(CharSequence cs)
+ {
+ buffer.append(cs);
+ }
+
+ /**
+ * Resets the response to a clean state so it can be reused to save on garbage.
+ */
+ @Override
+ public void reset()
+ {
+ buffer.clear();
+ }
+
+ @Override
+ public void write(byte[] array)
+ {
+ throw new UnsupportedOperationException("Cannot write binary data.");
+ }
+
+ @Override
+ public void write(byte[] array, int offset, int length)
+ {
+ throw new UnsupportedOperationException("Cannot write binary data.");
+ }
+
+ @Override
+ public Object getContainerResponse()
+ {
+ return originalResponse.getContainerResponse();
+ }
+
+ @Override
+ public void addCookie(Cookie cookie)
+ {
+ originalResponse.addCookie(cookie);
+ }
+
+ @Override
+ public void clearCookie(Cookie cookie)
+ {
+ originalResponse.clearCookie(cookie);
+ }
+
+ @Override
+ public void setHeader(String name, String value)
+ {
+ originalResponse.setHeader(name, value);
+ }
+
+ @Override
+ public void addHeader(String name, String value)
+ {
+ originalResponse.addHeader(name, value);
+ }
+
+ @Override
+ public void setDateHeader(String name, Time date)
+ {
+ originalResponse.setDateHeader(name, date);
+ }
+
+ @Override
+ public void setContentLength(long length)
+ {
+ originalResponse.setContentLength(length);
+ }
+
+ @Override
+ public void setContentType(String mimeType)
+ {
+ originalResponse.setContentType(mimeType);
+ }
+
+ @Override
+ public void setStatus(int sc)
+ {
+ originalResponse.setStatus(sc);
+ }
+
+ @Override
+ public void sendError(int sc, String msg)
+ {
+ originalResponse.sendError(sc, msg);
+ }
+
+ @Override
+ public String encodeRedirectURL(CharSequence url)
+ {
+ return originalResponse.encodeRedirectURL(url);
+ }
+
+ @Override
+ public void sendRedirect(String url)
+ {
+ originalResponse.sendRedirect(url);
+ }
+
+ @Override
+ public boolean isRedirect()
+ {
+ return originalResponse.isRedirect();
+ }
+
+ @Override
+ public void flush()
+ {
+ originalResponse.flush();
+ }
+ }
+
+ private void assertComponentsNotFrozen()
+ {
+ assertNotFrozen(componentsFrozen, Component.class);
+ }
+
+ private void assertNotFrozen(boolean frozen, Class<?> clazz)
+ {
+ if (frozen)
+ {
+ throw new IllegalStateException(Classes.simpleName(clazz) + "s can no " +
+ " longer be added");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
deleted file mode 100644
index e7048ec..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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.ajax;
-
-import java.util.Collection;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.Page;
-import org.apache.wicket.request.Response;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.apache.wicket.request.http.WebResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * An AbstractAjaxResponse that serializes itself to XML.
- * <p>
- * The elements of such response are:
- * <ul>
- * <li>priority-evaluate - an item of the prepend JavaScripts</li>
- * <li>component - the markup of the updated component</li>
- * <li>evaluate - an item of the onDomReady and append JavaScripts</li>
- * <li>header-contribution - all HeaderItems which have been contributed in components'
- * and their behaviors' #renderHead(Component, IHeaderResponse)</li>
- * </ul>
- * </p>
- */
-public abstract class XmlAjaxResponse extends AbstractAjaxResponse
-{
- private static final Logger LOG = LoggerFactory.getLogger(XmlAjaxResponse.class);
-
- /**
- * The name of the root element in the produced XML document.
- */
- public static final String START_ROOT_ELEMENT = "<ajax-response>";
- public static final String END_ROOT_ELEMENT = "</ajax-response>";
-
- public XmlAjaxResponse(final Page page)
- {
- super(page);
- }
-
- @Override
- public void setContentType(WebResponse response, String encoding)
- {
- response.setContentType("text/xml; charset=" + encoding);
- }
-
- @Override
- protected void writeHeader(Response response, String encoding)
- {
- response.write("<?xml version=\"1.0\" encoding=\"");
- response.write(encoding);
- response.write("\"?>");
- response.write(START_ROOT_ELEMENT);
- }
-
- @Override
- protected void writeComponent(Response response, String markupId, Component component, String encoding)
- {
- if (component.getRenderBodyOnly() == true)
- {
- throw new IllegalStateException(
- "Ajax render cannot be called on component that has setRenderBodyOnly enabled. Component: " +
- component.toString());
- }
-
- component.setOutputMarkupId(true);
-
- // Initialize temporary variables
- final Page page = component.findParent(Page.class);
- if (page == null)
- {
- // dont throw an exception but just ignore this component, somehow
- // it got removed from the page.
- LOG.warn("Component '{}' with markupid: '{}' not rendered because it was already removed from page",
- component, markupId);
- return;
- }
-
- // substitute our encoding response for the old one so we can capture
- // component's markup in a manner safe for transport inside CDATA block
- Response oldResponse = RequestCycle.get().setResponse(encodingBodyResponse);
-
- try
- {
- encodingBodyResponse.reset();
-
- page.startComponentRender(component);
-
- try
- {
- component.prepareForRender();
-
- // render any associated headers of the component
- writeHeaderContribution(response, component);
- }
- catch (RuntimeException e)
- {
- try
- {
- component.afterRender();
- }
- catch (RuntimeException e2)
- {
- // ignore this one could be a result off.
- }
- encodingBodyResponse.reset();
- throw e;
- }
-
- try
- {
- component.render();
- }
- catch (RuntimeException e)
- {
- encodingBodyResponse.reset();
- throw e;
- }
-
- page.endComponentRender(component);
- }
- finally
- {
- // Restore original response
- RequestCycle.get().setResponse(oldResponse);
- }
-
- response.write("<component id=\"");
- response.write(markupId);
- response.write("\" ><![CDATA[");
- response.write(encodingBodyResponse.getContents());
- response.write("]]></component>");
-
- encodingBodyResponse.reset();
- }
-
- @Override
- protected void writeFooter(Response response, String encoding)
- {
- response.write(END_ROOT_ELEMENT);
- }
-
- @Override
- protected void writeHeaderContribution(Response response)
- {
- if (encodingHeaderResponse.getContents().length() != 0)
- {
- response.write("<header-contribution>");
-
- // we need to write response as CDATA and parse it on client,
- // because konqueror crashes when there is a <script> element
- response.write("<![CDATA[<head xmlns:wicket=\"http://wicket.apache.org\">");
- response.write(encodingHeaderResponse.getContents());
- response.write("</head>]]>");
- response.write("</header-contribution>");
- }
- }
-
- @Override
- protected void writeNormalEvaluations(final Response response, final Collection<CharSequence> scripts)
- {
- writeEvaluations(response, "evaluate", scripts);
-
- }
-
- @Override
- protected void writePriorityEvaluations(Response response, Collection<CharSequence> scripts)
- {
- writeEvaluations(response, "priority-evaluate", scripts);
- }
-
- private void writeEvaluations(final Response response, String elementName, Collection<CharSequence> scripts)
- {
- if (scripts.size() > 0)
- {
- StringBuilder combinedScript = new StringBuilder(1024);
- for (CharSequence script : scripts)
- {
- combinedScript.append("(function(){").append(script).append("})();");
- }
- writeEvaluation(elementName, response, combinedScript);
- }
- }
-
- /**
- * @param invocation
- * type of invocation tag, usually {@literal evaluate} or
- * {@literal priority-evaluate}
- * @param response
- * @param js
- */
- private void writeEvaluation(final String invocation, final Response response, final CharSequence js)
- {
- CharSequence javascript = js;
-
- // encode the response if needed
- if (needsEncoding(js))
- {
- javascript = encode(js);
- }
-
- response.write("<");
- response.write(invocation);
- response.write(">");
-
- response.write("<![CDATA[");
- response.write(javascript);
- response.write("]]>");
-
- response.write("</");
- response.write(invocation);
- response.write(">");
-
- encodingBodyResponse.reset();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
new file mode 100644
index 0000000..d3f6d73
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
@@ -0,0 +1,234 @@
+/*
+ * 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.ajax;
+
+import java.util.Collection;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.util.string.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link PartialPageUpdate} that serializes itself to XML.
+ */
+public abstract class XmlPartialPageUpdate extends PartialPageUpdate
+{
+ private static final Logger LOG = LoggerFactory.getLogger(XmlPartialPageUpdate.class);
+
+ /**
+ * The name of the root element in the produced XML document.
+ */
+ public static final String START_ROOT_ELEMENT = "<ajax-response>";
+ public static final String END_ROOT_ELEMENT = "</ajax-response>";
+
+ public XmlPartialPageUpdate(final Page page)
+ {
+ super(page);
+ }
+
+ @Override
+ public void setContentType(WebResponse response, String encoding)
+ {
+ response.setContentType("text/xml; charset=" + encoding);
+ }
+
+ @Override
+ protected void writeHeader(Response response, String encoding)
+ {
+ response.write("<?xml version=\"1.0\" encoding=\"");
+ response.write(encoding);
+ response.write("\"?>");
+ response.write(START_ROOT_ELEMENT);
+ }
+
+ @Override
+ protected void writeComponent(Response response, String markupId, Component component, String encoding)
+ {
+ if (component.getRenderBodyOnly() == true)
+ {
+ throw new IllegalStateException(
+ "A partial update is not possible for a component that has renderBodyOnly enabled. Component: " +
+ component.toString());
+ }
+
+ component.setOutputMarkupId(true);
+
+ // Initialize temporary variables
+ final Page page = component.findParent(Page.class);
+ if (page == null)
+ {
+ // dont throw an exception but just ignore this component, somehow
+ // it got removed from the page.
+ LOG.warn("Component '{}' with markupid: '{}' not rendered because it was already removed from page",
+ component, markupId);
+ return;
+ }
+
+ // substitute our encoding response for the old one so we can capture
+ // component's markup in a manner safe for transport inside CDATA block
+ Response oldResponse = RequestCycle.get().setResponse(encodingBodyResponse);
+
+ try
+ {
+ encodingBodyResponse.reset();
+
+ page.startComponentRender(component);
+
+ try
+ {
+ component.prepareForRender();
+
+ // render any associated headers of the component
+ writeHeaderContribution(response, component);
+ }
+ catch (RuntimeException e)
+ {
+ try
+ {
+ component.afterRender();
+ }
+ catch (RuntimeException e2)
+ {
+ // ignore this one could be a result off.
+ }
+ encodingBodyResponse.reset();
+ throw e;
+ }
+
+ try
+ {
+ component.render();
+ }
+ catch (RuntimeException e)
+ {
+ encodingBodyResponse.reset();
+ throw e;
+ }
+
+ page.endComponentRender(component);
+ }
+ finally
+ {
+ // Restore original response
+ RequestCycle.get().setResponse(oldResponse);
+ }
+
+ response.write("<component id=\"");
+ response.write(markupId);
+ response.write("\" ><![CDATA[");
+ response.write(encode(encodingBodyResponse.getContents()));
+ response.write("]]></component>");
+
+ encodingBodyResponse.reset();
+ }
+
+ @Override
+ protected void writeFooter(Response response, String encoding)
+ {
+ response.write(END_ROOT_ELEMENT);
+ }
+
+ @Override
+ protected void writeHeaderContribution(Response response)
+ {
+ if (encodingHeaderResponse.getContents().length() != 0)
+ {
+ response.write("<header-contribution>");
+
+ // we need to write response as CDATA and parse it on client,
+ // because konqueror crashes when there is a <script> element
+ response.write("<![CDATA[<head xmlns:wicket=\"http://wicket.apache.org\">");
+ response.write(encode(encodingHeaderResponse.getContents()));
+ response.write("</head>]]>");
+ response.write("</header-contribution>");
+ }
+ }
+
+ @Override
+ protected void writeNormalEvaluations(final Response response, final Collection<CharSequence> scripts)
+ {
+ writeEvaluations(response, "evaluate", scripts);
+
+ }
+
+ @Override
+ protected void writePriorityEvaluations(Response response, Collection<CharSequence> scripts)
+ {
+ writeEvaluations(response, "priority-evaluate", scripts);
+ }
+
+ private void writeEvaluations(final Response response, String elementName, Collection<CharSequence> scripts)
+ {
+ if (scripts.size() > 0)
+ {
+ StringBuilder combinedScript = new StringBuilder(1024);
+ for (CharSequence script : scripts)
+ {
+ combinedScript.append("(function(){").append(script).append("})();");
+ }
+ writeEvaluation(elementName, response, combinedScript);
+ }
+ }
+
+ /**
+ * @param invocation
+ * type of invocation tag, usually {@literal evaluate} or
+ * {@literal priority-evaluate}
+ * @param response
+ * @param js
+ */
+ private void writeEvaluation(final String invocation, final Response response, final CharSequence js)
+ {
+ response.write("<");
+ response.write(invocation);
+ response.write(">");
+
+ response.write("<![CDATA[");
+ response.write(encode(js));
+ response.write("]]>");
+
+ response.write("</");
+ response.write(invocation);
+ response.write(">");
+
+ encodingBodyResponse.reset();
+ }
+
+ protected CharSequence encode(CharSequence str)
+ {
+ /*
+ * TODO Post 1.2: we can improve this by keeping a buffer of at least 3 characters and
+ * checking that buffer so that we can narrow down escaping occurring only for ']]>'
+ * sequence, or at least for ]] if ] is the last char in this buffer.
+ *
+ * but this improvement will only work if we write first and encode later instead of working
+ * on fragments sent to write
+ */
+ if (Strings.indexOf(str, ']') >= 0) {
+ str = Strings.replaceAll(str, "]]>", "]]]]><![CDATA[>").toString();
+ }
+
+ return str;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/main/java/org/apache/wicket/response/filter/XmlCleaningResponseFilter.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/response/filter/XmlCleaningResponseFilter.java b/wicket-core/src/main/java/org/apache/wicket/response/filter/XmlCleaningResponseFilter.java
index 5552552..8920ece 100644
--- a/wicket-core/src/main/java/org/apache/wicket/response/filter/XmlCleaningResponseFilter.java
+++ b/wicket-core/src/main/java/org/apache/wicket/response/filter/XmlCleaningResponseFilter.java
@@ -16,7 +16,7 @@
*/
package org.apache.wicket.response.filter;
-import org.apache.wicket.ajax.XmlAjaxResponse;
+import org.apache.wicket.ajax.XmlPartialPageUpdate;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,7 +70,7 @@ public class XmlCleaningResponseFilter implements IResponseFilter
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ajax-response>
int min = Math.min(150, responseBuffer.length());
String firstNChars = responseBuffer.substring(0, min);
- return firstNChars.contains(XmlAjaxResponse.START_ROOT_ELEMENT);
+ return firstNChars.contains(XmlPartialPageUpdate.START_ROOT_ELEMENT);
}
/**
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-core/src/test/java/org/apache/wicket/response/filter/XmlCleaningResponseFilterTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/response/filter/XmlCleaningResponseFilterTest.java b/wicket-core/src/test/java/org/apache/wicket/response/filter/XmlCleaningResponseFilterTest.java
index 1c648b1..c255a59 100644
--- a/wicket-core/src/test/java/org/apache/wicket/response/filter/XmlCleaningResponseFilterTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/response/filter/XmlCleaningResponseFilterTest.java
@@ -16,8 +16,8 @@
*/
package org.apache.wicket.response.filter;
-import static org.apache.wicket.ajax.XmlAjaxResponse.END_ROOT_ELEMENT;
-import static org.apache.wicket.ajax.XmlAjaxResponse.START_ROOT_ELEMENT;
+import static org.apache.wicket.ajax.XmlPartialPageUpdate.END_ROOT_ELEMENT;
+import static org.apache.wicket.ajax.XmlPartialPageUpdate.START_ROOT_ELEMENT;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.junit.Assert;
import org.junit.Test;
http://git-wip-us.apache.org/repos/asf/wicket/blob/7c40e4da/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
index 2a14374..6cbda67 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
@@ -23,8 +23,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
-import org.apache.wicket.ajax.AbstractAjaxResponse;
-import org.apache.wicket.ajax.XmlAjaxResponse;
+import org.apache.wicket.ajax.PartialPageUpdate;
+import org.apache.wicket.ajax.XmlPartialPageUpdate;
import org.apache.wicket.core.request.handler.logger.PageLogData;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.request.ILogData;
@@ -41,8 +41,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * An extension of AjaxRequestTarget that also supports pushing data from the server to the
- * client.
+ * A handler of WebSocket requests.
*
* @since 6.0
*/
@@ -54,11 +53,11 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
private final IWebSocketConnection connection;
- private final AbstractAjaxResponse ajaxResponse;
+ private final PartialPageUpdate update;
/**
* A flag indicating that there is data to be written to construct an <ajax-response>
- * There is no need to push empty Ajax response if only #push() is used
+ * There is no need to push empty response if only #push() is used
*/
private final AtomicBoolean hasData = new AtomicBoolean(false);
@@ -68,7 +67,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
{
this.page = Args.notNull(component, "component").getPage();
this.connection = Args.notNull(connection, "connection");
- this.ajaxResponse = new XmlAjaxResponse(page)
+ this.update = new XmlPartialPageUpdate(page)
{
@Override
protected void fireOnAfterRespondListeners(Response response)
@@ -126,7 +125,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
public void add(Component component, String markupId)
{
hasData.set(true);
- ajaxResponse.add(component, markupId);
+ update.add(component, markupId);
}
@Override
@@ -167,20 +166,20 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
public void appendJavaScript(CharSequence javascript)
{
hasData.set(true);
- ajaxResponse.appendJavaScript(javascript);
+ update.appendJavaScript(javascript);
}
@Override
public void prependJavaScript(CharSequence javascript)
{
hasData.set(true);
- ajaxResponse.prependJavaScript(javascript);
+ update.prependJavaScript(javascript);
}
@Override
public Collection<? extends Component> getComponents()
{
- return ajaxResponse.getComponents();
+ return update.getComponents();
}
@Override
@@ -200,7 +199,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
public IHeaderResponse getHeaderResponse()
{
hasData.set(true);
- return ajaxResponse.getHeaderResponse();
+ return update.getHeaderResponse();
}
@Override
@@ -258,7 +257,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
{
if (hasData.get())
{
- ajaxResponse.writeTo(requestCycle.getResponse(), "UTF-8");
+ update.writeTo(requestCycle.getResponse(), "UTF-8");
}
}
@@ -270,7 +269,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
logData = new PageLogData(page);
}
- ajaxResponse.detach(requestCycle);
+ update.detach(requestCycle);
hasData.set(false);
}
}
[2/2] wicket git commit: WICKET-5929 remove ajax from page update
Posted by sv...@apache.org.
WICKET-5929 remove ajax from page update
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/470f2a28
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/470f2a28
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/470f2a28
Branch: refs/heads/master
Commit: 470f2a286a51e05f78251f6d8f9a6837d42b2125
Parents: 7c40e4d
Author: Sven Meier <sv...@apache.org>
Authored: Sat Jun 27 09:00:38 2015 +0200
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jun 27 09:03:49 2015 +0200
----------------------------------------------------------------------
.../apache/wicket/ajax/AjaxRequestHandler.java | 75 ++++++++++----------
.../apache/wicket/ajax/PartialPageUpdate.java | 11 +--
.../wicket/ajax/XmlPartialPageUpdate.java | 2 +-
.../ws/api/WebSocketRequestHandler.java | 14 +---
4 files changed, 44 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/470f2a28/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
index 439319d..f7ab416 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java
@@ -81,10 +81,9 @@ public class AjaxRequestHandler implements AjaxRequestTarget
{
/**
- * A POJO-like that collects the data for the Ajax response written to the client and serializes
- * it to specific String-based format (XML, JSON, ...).
+ * Collector of page updates.
*/
- private final PartialPageUpdate responseObject;
+ private final PartialPageUpdate update;
/** a list of listeners */
private List<AjaxRequestTarget.IListener> listeners = null;
@@ -111,8 +110,28 @@ public class AjaxRequestHandler implements AjaxRequestTarget
{
this.page = Args.notNull(page, "page");
- responseObject = new XmlPartialPageUpdate(page)
+ update = new XmlPartialPageUpdate(page)
{
+ /**
+ * Freezes the {@link AjaxRequestHandler#listeners} before firing the event and
+ * un-freezes them afterwards to allow components to add more
+ * {@link AjaxRequestTarget.IListener}s for the second event.
+ */
+ @Override
+ protected void onBeforeRespond(final Response response)
+ {
+ listenersFrozen = true;
+
+ if (listeners != null)
+ {
+ for (AjaxRequestTarget.IListener listener : listeners)
+ {
+ listener.onBeforeRespond(markupIdToComponent, AjaxRequestHandler.this);
+ }
+ }
+
+ listenersFrozen = false;
+ }
/**
* Freezes the {@link AjaxRequestHandler#listeners}, and does not un-freeze them as the
@@ -122,7 +141,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
* the response to write to
*/
@Override
- protected void fireOnAfterRespondListeners(final Response response)
+ protected void onAfterRespond(final Response response)
{
listenersFrozen = true;
@@ -148,28 +167,6 @@ public class AjaxRequestHandler implements AjaxRequestTarget
}
}
}
-
- /**
- * Freezes the {@link AjaxRequestHandler#listeners} before firing the event and
- * un-freezes them afterwards to allow components to add more
- * {@link AjaxRequestTarget.IListener}s for the second event.
- */
- @Override
- protected void fireOnBeforeRespondListeners()
- {
- listenersFrozen = true;
-
- if (listeners != null)
- {
- for (AjaxRequestTarget.IListener listener : listeners)
- {
- listener.onBeforeRespond(markupIdToComponent, AjaxRequestHandler.this);
- }
- }
-
- listenersFrozen = false;
- }
-
};
}
@@ -236,13 +233,13 @@ public class AjaxRequestHandler implements AjaxRequestTarget
@Override
public void add(Component component, String markupId)
{
- responseObject.add(component, markupId);
+ update.add(component, markupId);
}
@Override
public final Collection<? extends Component> getComponents()
{
- return responseObject.getComponents();
+ return update.getComponents();
}
@Override
@@ -261,7 +258,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
@Override
public final void appendJavaScript(CharSequence javascript)
{
- responseObject.appendJavaScript(javascript);
+ update.appendJavaScript(javascript);
}
/**
@@ -275,7 +272,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
logData = new PageLogData(page);
}
- responseObject.detach(requestCycle);
+ update.detach(requestCycle);
}
/**
@@ -287,7 +284,7 @@ public class AjaxRequestHandler implements AjaxRequestTarget
if (obj instanceof AjaxRequestHandler)
{
AjaxRequestHandler that = (AjaxRequestHandler)obj;
- return responseObject.equals(that.responseObject);
+ return update.equals(that.update);
}
return false;
}
@@ -299,14 +296,14 @@ public class AjaxRequestHandler implements AjaxRequestTarget
public int hashCode()
{
int result = "AjaxRequestHandler".hashCode();
- result += responseObject.hashCode() * 17;
+ result += update.hashCode() * 17;
return result;
}
@Override
public final void prependJavaScript(CharSequence javascript)
{
- responseObject.prependJavaScript(javascript);
+ update.prependJavaScript(javascript);
}
@Override
@@ -350,20 +347,20 @@ public class AjaxRequestHandler implements AjaxRequestTarget
final String encoding = app.getRequestCycleSettings().getResponseRequestEncoding();
// Set content type based on markup type for page
- responseObject.setContentType(response, encoding);
+ update.setContentType(response, encoding);
// Make sure it is not cached by a client
response.disableCaching();
final StringResponse bodyResponse = new StringResponse();
- responseObject.writeTo(bodyResponse, encoding);
+ update.writeTo(bodyResponse, encoding);
CharSequence filteredResponse = invokeResponseFilters(bodyResponse);
response.write(filteredResponse);
}
private boolean shouldRedirectToPage(IRequestCycle requestCycle)
{
- if (responseObject.containsPage())
+ if (update.containsPage())
{
return true;
}
@@ -411,13 +408,13 @@ public class AjaxRequestHandler implements AjaxRequestTarget
@Override
public String toString()
{
- return "[AjaxRequestHandler@" + hashCode() + " responseObject [" + responseObject + "]";
+ return "[AjaxRequestHandler@" + hashCode() + " responseObject [" + update + "]";
}
@Override
public IHeaderResponse getHeaderResponse()
{
- return responseObject.getHeaderResponse();
+ return update.getHeaderResponse();
}
/**
http://git-wip-us.apache.org/repos/asf/wicket/blob/470f2a28/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
index 5970f38..35ea016 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/PartialPageUpdate.java
@@ -153,13 +153,12 @@ public abstract class PartialPageUpdate
{
writeHeader(response, encoding);
- // invoke onbeforerespond event on listeners
- fireOnBeforeRespondListeners();
+ onBeforeRespond(response);
// process added components
writeComponents(response, encoding);
- fireOnAfterRespondListeners(response);
+ onAfterRespond(response);
// queue up prepend javascripts. unlike other steps these are executed out of order so that
// components can contribute them from inside their onbeforerender methods.
@@ -175,9 +174,11 @@ public abstract class PartialPageUpdate
writeFooter(response, encoding);
}
- protected abstract void fireOnAfterRespondListeners(Response response);
+ protected void onBeforeRespond(Response response) {
+ }
- protected abstract void fireOnBeforeRespondListeners();
+ protected void onAfterRespond(Response response) {
+ }
/**
* @param response
http://git-wip-us.apache.org/repos/asf/wicket/blob/470f2a28/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
index d3f6d73..fb157c5 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlPartialPageUpdate.java
@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
/**
* A {@link PartialPageUpdate} that serializes itself to XML.
*/
-public abstract class XmlPartialPageUpdate extends PartialPageUpdate
+public class XmlPartialPageUpdate extends PartialPageUpdate
{
private static final Logger LOG = LoggerFactory.getLogger(XmlPartialPageUpdate.class);
http://git-wip-us.apache.org/repos/asf/wicket/blob/470f2a28/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
index 6cbda67..5528f76 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketRequestHandler.java
@@ -29,7 +29,6 @@ import org.apache.wicket.core.request.handler.logger.PageLogData;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.request.ILogData;
import org.apache.wicket.request.IRequestCycle;
-import org.apache.wicket.request.Response;
import org.apache.wicket.request.component.IRequestablePage;
import org.apache.wicket.request.http.WebRequest;
import org.apache.wicket.request.mapper.parameter.PageParameters;
@@ -67,18 +66,7 @@ public class WebSocketRequestHandler implements IWebSocketRequestHandler
{
this.page = Args.notNull(component, "component").getPage();
this.connection = Args.notNull(connection, "connection");
- this.update = new XmlPartialPageUpdate(page)
- {
- @Override
- protected void fireOnAfterRespondListeners(Response response)
- {
- }
-
- @Override
- protected void fireOnBeforeRespondListeners()
- {
- }
- };
+ this.update = new XmlPartialPageUpdate(page);
}
@Override