diff options
9 files changed, 194 insertions, 96 deletions
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index b87aaa278b..ba1b3cadb6 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -2394,8 +2394,7 @@ public abstract class AbstractCommunicationManager implements Serializable { // Use the same logic as for determined roots BootstrapHandler bootstrapHandler = getBootstrapHandler(); BootstrapContext context = bootstrapHandler.createContext( - combinedRequest, response, application, root.getRootId(), - null); + combinedRequest, response, application, root.getRootId()); String widgetset = context.getWidgetsetName(); String theme = context.getThemeName(); diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapFragmentResponse.java b/src/com/vaadin/terminal/gwt/server/BootstrapFragmentResponse.java new file mode 100644 index 0000000000..bcf098b5aa --- /dev/null +++ b/src/com/vaadin/terminal/gwt/server/BootstrapFragmentResponse.java @@ -0,0 +1,28 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.server; + +import java.util.List; + +import org.jsoup.nodes.Node; + +import com.vaadin.Application; +import com.vaadin.terminal.WrappedRequest; + +public class BootstrapFragmentResponse extends BootstrapResponse { + private final List<Node> fragmentNodes; + + public BootstrapFragmentResponse(BootstrapHandler handler, + WrappedRequest request, List<Node> fragmentNodes, + Application application, Integer rootId) { + super(handler, request, application, rootId); + this.fragmentNodes = fragmentNodes; + } + + public List<Node> getFragmentNodes() { + return fragmentNodes; + } + +} diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java index 372ec694e6..bc3b7aa7a0 100644 --- a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java +++ b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java @@ -8,7 +8,9 @@ import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Serializable; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -19,6 +21,7 @@ import org.jsoup.nodes.DataNode; import org.jsoup.nodes.Document; import org.jsoup.nodes.DocumentType; import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; import org.jsoup.parser.Tag; import com.vaadin.Application; @@ -39,14 +42,14 @@ public abstract class BootstrapHandler implements RequestHandler { protected class BootstrapContext implements Serializable { private final WrappedResponse response; - private final BootstrapResponse bootstrapResponse; + private final BootstrapFragmentResponse bootstrapResponse; private String widgetsetName; private String themeName; private String appId; public BootstrapContext(WrappedResponse response, - BootstrapResponse bootstrapResponse) { + BootstrapFragmentResponse bootstrapResponse) { this.response = response; this.bootstrapResponse = bootstrapResponse; } @@ -98,7 +101,7 @@ public abstract class BootstrapHandler implements RequestHandler { return appId; } - public BootstrapResponse getBootstrapResponse() { + public BootstrapFragmentResponse getBootstrapResponse() { return bootstrapResponse; } @@ -124,29 +127,21 @@ public abstract class BootstrapHandler implements RequestHandler { } try { - Map<String, Object> headers = new LinkedHashMap<String, Object>(); BootstrapContext context = createContext(request, response, - application, rootId, headers); - BootstrapResponse bootstrapResponse = context - .getBootstrapResponse(); - + application, rootId); setupMainDiv(context); DeploymentConfiguration deploymentConfiguration = request .getDeploymentConfiguration(); - boolean standalone = deploymentConfiguration.isStandalone(request); - if (standalone) { - setupStandaloneDocument(context); - deploymentConfiguration.getVaadinContext() - .fireModifyBootstrapEvent(bootstrapResponse); - sendBootstrapHeaders(response, headers); - writeBootstrapPage(response, bootstrapResponse.getDocument()); - } else { - deploymentConfiguration.getVaadinContext() - .fireModifyBootstrapEvent(bootstrapResponse); - writeBootstrapPage(response, - bootstrapResponse.getApplicationTag()); - } + + VaadinContext vContext = deploymentConfiguration.getVaadinContext(); + BootstrapFragmentResponse fragmentResponse = context + .getBootstrapResponse(); + vContext.fireModifyBootstrapEvent(fragmentResponse); + + String html = getBootstrapHtml(context); + + writeBootstrapPage(response, html); } catch (JSONException e) { writeError(response, e); } @@ -154,6 +149,46 @@ public abstract class BootstrapHandler implements RequestHandler { return true; } + private String getBootstrapHtml(BootstrapContext context) { + WrappedRequest request = context.getRequest(); + WrappedResponse response = context.getResponse(); + DeploymentConfiguration deploymentConfiguration = request + .getDeploymentConfiguration(); + VaadinContext vContext = deploymentConfiguration.getVaadinContext(); + BootstrapFragmentResponse fragmentResponse = context + .getBootstrapResponse(); + + if (deploymentConfiguration.isStandalone(request)) { + Map<String, Object> headers = new LinkedHashMap<String, Object>(); + Document document = Document.createShell(""); + BootstrapPageResponse pageResponse = new BootstrapPageResponse( + this, request, document, headers, context.getApplication(), + context.getRootId()); + List<Node> fragmentNodes = fragmentResponse.getFragmentNodes(); + Element body = document.body(); + for (Node node : fragmentNodes) { + body.appendChild(node); + } + + setupStandaloneDocument(context, pageResponse); + vContext.fireModifyBootstrapEvent(pageResponse); + + sendBootstrapHeaders(response, headers); + + return document.outerHtml(); + } else { + StringBuilder sb = new StringBuilder(); + for (Node node : fragmentResponse.getFragmentNodes()) { + if (sb.length() != 0) { + sb.append('\n'); + } + sb.append(node.outerHtml()); + } + + return sb.toString(); + } + } + private void sendBootstrapHeaders(WrappedResponse response, Map<String, Object> headers) { Set<Entry<String, Object>> entrySet = headers.entrySet(); @@ -170,17 +205,17 @@ public abstract class BootstrapHandler implements RequestHandler { } } - private void writeBootstrapPage(WrappedResponse response, Element dom) + private void writeBootstrapPage(WrappedResponse response, String html) throws IOException { response.setContentType("text/html"); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( response.getOutputStream(), "UTF-8")); - writer.append(dom.outerHtml()); + writer.append(html); writer.close(); } - private void setupStandaloneDocument(BootstrapContext context) { - BootstrapResponse response = context.getBootstrapResponse(); + private void setupStandaloneDocument(BootstrapContext context, + BootstrapPageResponse response) { response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); @@ -229,22 +264,10 @@ public abstract class BootstrapHandler implements RequestHandler { } public BootstrapContext createContext(WrappedRequest request, - WrappedResponse response, Application application, Integer rootId, - Map<String, Object> headers) { - boolean standalone = request.getDeploymentConfiguration().isStandalone( - request); - Document document; - Element applicationTag; - if (standalone) { - document = Document.createShell(""); - applicationTag = document.body(); - } else { - document = null; - applicationTag = new Element(Tag.valueOf("div"), ""); - } + WrappedResponse response, Application application, Integer rootId) { BootstrapContext context = new BootstrapContext(response, - new BootstrapResponse(this, request, document, applicationTag, - headers, application, rootId)); + new BootstrapFragmentResponse(this, request, new ArrayList<Node>(), + application, rootId)); return context; } @@ -305,10 +328,10 @@ public abstract class BootstrapHandler implements RequestHandler { + context.getApplication().getClass().getSimpleName(); String classNames = "v-app " + appClass; + List<Node> fragmentNodes = context.getBootstrapResponse() + .getFragmentNodes(); - Element applicationTag = context.getBootstrapResponse() - .getApplicationTag(); - Element mainDiv = applicationTag.appendElement("div"); + Element mainDiv = new Element(Tag.valueOf("div"), ""); mainDiv.attr("id", context.getAppId()); mainDiv.addClass(classNames); if (style != null && style.length() != 0) { @@ -317,6 +340,7 @@ public abstract class BootstrapHandler implements RequestHandler { mainDiv.appendElement("div").addClass("v-app-loading"); mainDiv.appendElement("noscript") .append("You have to enable javascript in your browser to use an application built with Vaadin."); + fragmentNodes.add(mainDiv); WrappedRequest request = context.getRequest(); @@ -325,19 +349,19 @@ public abstract class BootstrapHandler implements RequestHandler { String staticFileLocation = deploymentConfiguration .getStaticFileLocation(request); - applicationTag - .appendElement("iframe") - .attr("tabIndex", "-1") - .attr("id", "__gwt_historyFrame") - .attr("style", - "position:absolute;width:0;height:0;border:0;overflow:hidden") - .attr("src", "javascript:false"); + fragmentNodes + .add(new Element(Tag.valueOf("iframe"), "") + .attr("tabIndex", "-1") + .attr("id", "__gwt_historyFrame") + .attr("style", + "position:absolute;width:0;height:0;border:0;overflow:hidden") + .attr("src", "javascript:false")); String bootstrapLocation = staticFileLocation + "/VAADIN/vaadinBootstrap.js"; - applicationTag.appendElement("script").attr("type", "text/javascript") - .attr("src", bootstrapLocation); - Element mainScriptTag = applicationTag.appendElement("script").attr( + fragmentNodes.add(new Element(Tag.valueOf("script"), "").attr("type", + "text/javascript").attr("src", bootstrapLocation)); + Element mainScriptTag = new Element(Tag.valueOf("script"), "").attr( "type", "text/javascript"); StringBuilder builder = new StringBuilder(); @@ -351,6 +375,8 @@ public abstract class BootstrapHandler implements RequestHandler { builder.append("//]]>"); mainScriptTag.appendChild(new DataNode(builder.toString(), mainScriptTag.baseUri())); + fragmentNodes.add(mainScriptTag); + } protected void appendMainScriptTagContents(BootstrapContext context, diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapListener.java b/src/com/vaadin/terminal/gwt/server/BootstrapListener.java index 54bd13c25a..d80e626cc1 100644 --- a/src/com/vaadin/terminal/gwt/server/BootstrapListener.java +++ b/src/com/vaadin/terminal/gwt/server/BootstrapListener.java @@ -7,5 +7,7 @@ package com.vaadin.terminal.gwt.server; import java.util.EventListener; public interface BootstrapListener extends EventListener { - public void modifyBootstrap(BootstrapResponse response); + public void modifyBootstrapFragment(BootstrapFragmentResponse response); + + public void modifyBootstrapPage(BootstrapPageResponse response); } diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapPageResponse.java b/src/com/vaadin/terminal/gwt/server/BootstrapPageResponse.java new file mode 100644 index 0000000000..802238ac62 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/server/BootstrapPageResponse.java @@ -0,0 +1,39 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.server; + +import java.util.Map; + +import org.jsoup.nodes.Document; + +import com.vaadin.Application; +import com.vaadin.terminal.WrappedRequest; + +public class BootstrapPageResponse extends BootstrapResponse { + + private final Map<String, Object> headers; + private final Document document; + + public BootstrapPageResponse(BootstrapHandler handler, + WrappedRequest request, Document document, + Map<String, Object> headers, Application application, Integer rootId) { + super(handler, request, application, rootId); + this.headers = headers; + this.document = document; + } + + public void setHeader(String name, String value) { + headers.put(name, value); + } + + public void setDateHeader(String name, long timestamp) { + headers.put(name, Long.valueOf(timestamp)); + } + + public Document getDocument() { + return document; + } + +} diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java b/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java index 37b59989f6..88bd58593d 100644 --- a/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java +++ b/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java @@ -5,43 +5,24 @@ package com.vaadin.terminal.gwt.server; import java.util.EventObject; -import java.util.Map; - -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; import com.vaadin.Application; import com.vaadin.terminal.WrappedRequest; import com.vaadin.ui.Root; -public class BootstrapResponse extends EventObject { - private final Document document; +public abstract class BootstrapResponse extends EventObject { private final WrappedRequest request; - private final Map<String, Object> headers; - private final Element applicationTag; private final Application application; private final Integer rootId; public BootstrapResponse(BootstrapHandler handler, WrappedRequest request, - Document document, Element applicationTag, - Map<String, Object> headers, Application application, Integer rootId) { + Application application, Integer rootId) { super(handler); this.request = request; - this.document = document; - this.applicationTag = applicationTag; - this.headers = headers; this.application = application; this.rootId = rootId; } - public void setHeader(String name, String value) { - headers.put(name, value); - } - - public void setDateHeader(String name, long timestamp) { - headers.put(name, Long.valueOf(timestamp)); - } - public BootstrapHandler getBootstrapHandler() { return (BootstrapHandler) getSource(); } @@ -50,14 +31,6 @@ public class BootstrapResponse extends EventObject { return request; } - public Document getDocument() { - return document; - } - - public Element getApplicationTag() { - return applicationTag; - } - public Application getApplication() { return application; } diff --git a/src/com/vaadin/terminal/gwt/server/VaadinContext.java b/src/com/vaadin/terminal/gwt/server/VaadinContext.java index f03044a872..3682c0ac4d 100644 --- a/src/com/vaadin/terminal/gwt/server/VaadinContext.java +++ b/src/com/vaadin/terminal/gwt/server/VaadinContext.java @@ -12,9 +12,12 @@ import com.vaadin.terminal.DeploymentConfiguration; import com.vaadin.tools.ReflectTools; public class VaadinContext { - private static final Method BOOTSTRAP_GENERATE_METHOD = ReflectTools - .findMethod(BootstrapListener.class, "modifyBootstrap", - BootstrapResponse.class); + private static final Method BOOTSTRAP_FRAGMENT_METHOD = ReflectTools + .findMethod(BootstrapListener.class, "modifyBootstrapFragment", + BootstrapFragmentResponse.class); + private static final Method BOOTSTRAP_PAGE_METHOD = ReflectTools + .findMethod(BootstrapListener.class, "modifyBootstrapPage", + BootstrapPageResponse.class); private final DeploymentConfiguration deploymentConfiguration; @@ -50,8 +53,10 @@ public class VaadinContext { } public void addBootstrapListener(BootstrapListener listener) { - eventRouter.addListener(BootstrapResponse.class, listener, - BOOTSTRAP_GENERATE_METHOD); + eventRouter.addListener(BootstrapFragmentResponse.class, listener, + BOOTSTRAP_FRAGMENT_METHOD); + eventRouter.addListener(BootstrapPageResponse.class, listener, + BOOTSTRAP_PAGE_METHOD); } public void fireModifyBootstrapEvent(BootstrapResponse bootstrapResponse) { diff --git a/tests/testbench/com/vaadin/tests/vaadincontext/BoostrapModify.html b/tests/testbench/com/vaadin/tests/vaadincontext/BoostrapModify.html index d5ab5af108..84c02254b4 100644 --- a/tests/testbench/com/vaadin/tests/vaadincontext/BoostrapModify.html +++ b/tests/testbench/com/vaadin/tests/vaadincontext/BoostrapModify.html @@ -23,8 +23,13 @@ </tr> <tr> <td>assertText</td> - <td>//h1</td> - <td>This is a heading</td> + <td>//div[1]</td> + <td>Added by modifyBootstrapPage</td> +</tr> +<tr> + <td>assertText</td> + <td>//div[2]</td> + <td>Added by modifyBootstrapFragment</td> </tr> </tbody></table> </body> diff --git a/tests/testbench/com/vaadin/tests/vaadincontext/TestVaadinContextListener.java b/tests/testbench/com/vaadin/tests/vaadincontext/TestVaadinContextListener.java index fa2767a023..9d1fc6b6c3 100644 --- a/tests/testbench/com/vaadin/tests/vaadincontext/TestVaadinContextListener.java +++ b/tests/testbench/com/vaadin/tests/vaadincontext/TestVaadinContextListener.java @@ -4,7 +4,12 @@ package com.vaadin.tests.vaadincontext; +import org.jsoup.nodes.Element; +import org.jsoup.parser.Tag; + +import com.vaadin.terminal.gwt.server.BootstrapFragmentResponse; import com.vaadin.terminal.gwt.server.BootstrapListener; +import com.vaadin.terminal.gwt.server.BootstrapPageResponse; import com.vaadin.terminal.gwt.server.BootstrapResponse; import com.vaadin.terminal.gwt.server.VaadinContextEvent; import com.vaadin.terminal.gwt.server.VaadinContextListener; @@ -15,11 +20,27 @@ public class TestVaadinContextListener implements VaadinContextListener { public void contextCreated(VaadinContextEvent event) { event.getVaadinContext().addBootstrapListener(new BootstrapListener() { @Override - public void modifyBootstrap(BootstrapResponse response) { + public void modifyBootstrapFragment( + BootstrapFragmentResponse response) { + if (shouldModify(response)) { + Element heading = new Element(Tag.valueOf("div"), "") + .text("Added by modifyBootstrapFragment"); + response.getFragmentNodes().add(0, heading); + } + } + + private boolean shouldModify(BootstrapResponse response) { Root root = response.getRoot(); - if (root != null && root.getClass() == BoostrapModifyRoot.class) { - response.getApplicationTag().before( - "<h1>This is a heading</h1>"); + boolean shouldModify = root != null + && root.getClass() == BoostrapModifyRoot.class; + return shouldModify; + } + + @Override + public void modifyBootstrapPage(BootstrapPageResponse response) { + if (shouldModify(response)) { + response.getDocument().body().child(0) + .before("<div>Added by modifyBootstrapPage</div>"); } } }); |