All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.markup.html.WebPage Maven / Gradle / Ivy

Go to download

Pax Wicket Service is an OSGi extension of the Wicket framework, allowing for dynamic loading and unloading of Wicket components and pageSources.

There is a newer version: 5.0.0
Show newest version
/*
 * 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.markup.html;

import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.IPageMap;
import org.apache.wicket.IRequestTarget;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.Response;
import org.apache.wicket.Session;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.parser.filter.HtmlHeaderSectionHandler;
import org.apache.wicket.model.IModel;
import org.apache.wicket.protocol.http.WebRequestCycle;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.protocol.http.request.urlcompressing.UrlCompressingWebRequestProcessor;
import org.apache.wicket.protocol.http.request.urlcompressing.UrlCompressor;
import org.apache.wicket.request.target.component.BookmarkablePageRequestTarget;
import org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;
import org.apache.wicket.response.StringResponse;
import org.apache.wicket.util.lang.Objects;
import org.apache.wicket.util.string.JavascriptUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Base class for HTML pages. This subclass of Page simply returns HTML when asked for its markup
 * type. It also has a method which subclasses can use to retrieve a bookmarkable link to the
 * application's home page.
 * 

* WebPages can be constructed with any constructor when they are being used in a Wicket session, * but if you wish to link to a Page using a URL that is "bookmarkable" (which implies that the URL * will not have any session information encoded in it, and that you can call this page directly * without having a session first directly from your browser), you need to implement your Page with * a no-arg constructor or with a constructor that accepts a PageParameters argument (which wraps * any query string parameters for a request). In case the page has both constructors, the * constructor with PageParameters will be used. * * @author Jonathan Locke * @author Eelco Hillenius * @author Juergen Donnerstag * @author Gwyn Evans */ public class WebPage extends Page implements INewBrowserWindowListener { /** log. */ private static final Logger log = LoggerFactory.getLogger(WebPage.class); private static final long serialVersionUID = 1L; /** * Tries to determine whether this page was opened in a new window or tab. If it is (and this * checker were able to recognize that), a new page map is created for this page instance, so * that it will start using it's own history in sync with the browser window or tab. */ private static final class PageMapChecker extends AbstractBehavior implements IHeaderContributor { private static final long serialVersionUID = 1L; private final WebPage webPage; /** * Construct. * * @param webPage */ PageMapChecker(WebPage webPage) { this.webPage = webPage; } /** * @see org.apache.wicket.markup.html.IHeaderContributor#renderHead(IHeaderResponse) */ @Override public final void renderHead(final IHeaderResponse headResponse) { Response response = headResponse.getResponse(); final WebRequestCycle cycle = (WebRequestCycle)RequestCycle.get(); final IRequestTarget target = cycle.getRequestTarget(); // we don't want to render this for stateless pages if (webPage.isPageStateless()) { return; } IPageMap pageMap = webPage.getPageMap(); String name = pageMap.getName(); if (name == null) { name = "wicket:default"; } else { name = name.replace('"', '_'); } Session session = Session.get(); Session.PageMapAccessMetaData meta = session.getMetaData(Session.PAGEMAP_ACCESS_MDK); if (meta == null) { meta = new Session.PageMapAccessMetaData(); session.setMetaData(Session.PAGEMAP_ACCESS_MDK, meta); } boolean firstAccess = meta.add(pageMap); if (firstAccess) { // this is the first access to the pagemap, set window.name JavascriptUtils.writeOpenTag(response); response.write("if (window.name=='' || window.name.indexOf('wicket') > -1) { window.name=\""); response.write("wicket-" + name); response.write("\"; }"); JavascriptUtils.writeCloseTag(response); } else { // Here is our trickery to detect whether the current request // was made in a new window/ tab, in which case it should go in // a different page map so that we don't intermingle the history // of those windows CharSequence url = null; if (target instanceof IBookmarkablePageRequestTarget) { IBookmarkablePageRequestTarget current = (IBookmarkablePageRequestTarget)target; BookmarkablePageRequestTarget redirect = new BookmarkablePageRequestTarget( session.createAutoPageMapName(), current.getPageClass(), current.getPageParameters()); url = cycle.urlFor(redirect); } else { url = webPage.urlFor(INewBrowserWindowListener.INTERFACE); } JavascriptUtils.writeOpenTag(response); response.write("if (window.name=='' || (window.name.indexOf('wicket') > -1 && window.name!='" + "wicket-" + name + "')) { window.location=\""); response.write(url); response.write("\" + (window.location.hash != null ? window.location.hash : \"\"); }"); JavascriptUtils.writeCloseTag(response); } } } /** The resource references used for new window/tab support */ private static ResourceReference cookiesResource = new ResourceReference(WebPage.class, "cookies.js"); /** * The url compressor that will compress the urls by collapsing the component path and listener * interface */ private UrlCompressor compressor; /** * Constructor. Having this constructor public means that your page is 'bookmarkable' and hence * can be called/ created from anywhere. */ protected WebPage() { commonInit(); } /** * @see Page#Page(IModel) */ protected WebPage(final IModel model) { super(model); commonInit(); } /** * @see Page#Page(org.apache.wicket.IPageMap) */ protected WebPage(final IPageMap pageMap) { super(pageMap); commonInit(); } /** * @see Page#Page(org.apache.wicket.IPageMap, org.apache.wicket.model.IModel) */ protected WebPage(final IPageMap pageMap, final IModel model) { super(pageMap, model); commonInit(); } /** * Constructor which receives wrapped query string parameters for a request. Having this * constructor public means that your page is 'bookmarkable' and hence can be called/ created * from anywhere. For bookmarkable pages (as opposed to when you construct page instances * yourself, this constructor will be used in preference to a no-arg constructor, if both exist. * Note that nothing is done with the page parameters argument. This constructor is provided so * that tools such as IDEs will include it their list of suggested constructors for derived * classes. * * Please call this constructor (or the one with the pagemap) if you want to remember the * pageparameters {@link #getPageParameters()}. So that they are reused for stateless links. * * @param parameters * Wrapped query string parameters. */ protected WebPage(final PageParameters parameters) { super(parameters); commonInit(); } /** * Constructor which receives wrapped query string parameters for a request. Having this * constructor public means that your page is 'bookmarkable' and hence can be called/ created * from anywhere. For bookmarkable pages (as opposed to when you construct page instances * yourself, this constructor will be used in preference to a no-arg constructor, if both exist. * Note that nothing is done with the page parameters argument. This constructor is provided so * that tools such as IDEs will include it their list of suggested constructors for derived * classes. * * Please call this constructor (or the one without the pagemap) if you want to remember the * pageparameters {@link #getPageParameters()}. So that they are reused for stateless links. * * @param pageMap * The pagemap where the webpage needs to be constructed in. * @param parameters * Wrapped query string parameters. */ protected WebPage(final IPageMap pageMap, final PageParameters parameters) { super(pageMap, parameters); commonInit(); } /** * Gets the markup type for a WebPage, which is "html" by default. Support for pages in another * markup language, such as VXML, would require the creation of a different Page subclass in an * appropriate package under org.apache.wicket.markup. To support VXML (voice markup), one might * create the package org.apache.wicket.markup.vxml and a subclass of Page called VoicePage. * * @return Markup type for HTML */ @Override public String getMarkupType() { return "html"; } /** * This method is called when the compressing coding and response strategies are configured in * your Application object like this: * *

	 * protected IRequestCycleProcessor newRequestCycleProcessor()
	 * {
	 * 	return new UrlCompressingWebRequestProcessor();
	 * }
	 * 
* * @return The URLCompressor for this webpage. * * @since 1.2 * * @see UrlCompressingWebRequestProcessor * @see UrlCompressor */ public final UrlCompressor getUrlCompressor() { if (compressor == null) { compressor = new UrlCompressor(); setStatelessHint(false); } return compressor; } /** * @see org.apache.wicket.markup.html.INewBrowserWindowListener#onNewBrowserWindow() */ public void onNewBrowserWindow() { // if the browser reports a history of 0 then make a new webpage WebPage clonedPage = this; try { clonedPage = (WebPage)Objects.cloneObject(this); } catch (Exception e) { log.error("Page " + clonedPage + " couldn't be cloned to move to another pagemap", e); } final IPageMap map = getSession().createAutoPageMap(); clonedPage.moveToPageMap(map); setResponsePage(clonedPage); } /** * Common code executed by constructors. */ private void commonInit() { // if automatic multi window support is on, add a page checker instance if (getApplication().getPageSettings().getAutomaticMultiWindowSupport()) { add(new PageMapChecker(this)); } } /** * @see org.apache.wicket.Page#configureResponse() */ @Override protected void configureResponse() { super.configureResponse(); if (getWebRequestCycle().getResponse() instanceof WebResponse) { final WebResponse response = getWebRequestCycle().getWebResponse(); setHeaders(response); } } /** * Subclasses can override this to set there headers when the Page is being served. By default 2 * headers will be set * *
	 * response.setHeader("Pragma", "no-cache");
	 * response.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate");
	 * 
* * So if a Page wants to control this or doesn't want to set this info it should override this * method and don't call super. * * @param response * The WebResponse where set(Date)Header can be called on. */ protected void setHeaders(WebResponse response) { response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate"); // no-store } /** * @return The WebRequestCycle for this WebPage. */ protected final WebRequestCycle getWebRequestCycle() { return (WebRequestCycle)getRequestCycle(); } /** * Creates and returns a bookmarkable link to this application's home page. * * @param id * Name of link * @return Link to home page for this application */ protected final BookmarkablePageLink homePageLink(final String id) { return new BookmarkablePageLink(id, getApplication().getHomePage()); } /** * * @see org.apache.wicket.Component#onAfterRender() */ @Override protected void onAfterRender() { super.onAfterRender(); // only in development mode validate the headers if (Application.DEVELOPMENT.equals(getApplication().getConfigurationType())) { // Ignore if an exception and a redirect happened in between (e.g. // RestartResponseAtInterceptPageException) if (getRequestCycle().getResponsePage() == this) { validateHeaders(); } } } /** * Validate that each component which wanted to contribute to the header section actually was * able to do so. */ private void validateHeaders() { HtmlHeaderContainer header = (HtmlHeaderContainer)visitChildren(new IVisitor() { public Object component(Component component) { if (component instanceof HtmlHeaderContainer) { return component; } return IVisitor.CONTINUE_TRAVERSAL; } }); if (header == null) { // the markup must at least contain a tag for wicket to automatically // create a HtmlHeaderContainer. Log an error if no header container // was created but any of the components or behaviors want to contribute // something to the header. header = new HtmlHeaderContainer(HtmlHeaderSectionHandler.HEADER_ID); add(header); Response orgResponse = getRequestCycle().getResponse(); try { final StringResponse response = new StringResponse(); getRequestCycle().setResponse(response); // Render all header sections of all components on the page renderHead(header); // Make sure all Components interested in contributing to the header // and there attached behaviors are asked. final HtmlHeaderContainer finalHeader = header; visitChildren(new IVisitor() { /** * @see org.apache.wicket.Component.IVisitor#component(org.apache.wicket.Component) */ public Object component(Component component) { component.renderHead(finalHeader); return CONTINUE_TRAVERSAL; } }); response.close(); if (response.getBuffer().length() > 0) { // @TODO it is not yet working properly. JDo to fix it log.error("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); log.error("You probably forgot to add a or tag to your markup since no Header Container was \n" + "found but components were found which want to write to the section.\n" + response.getBuffer()); log.error("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); } } catch (Exception e) { // just swallow this exception, there isn't much we can do about. log.error("header/body check throws exception", e); } finally { this.remove(header); getRequestCycle().setResponse(orgResponse); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy