Package org.apache.wicket.markup.html

Source Code of org.apache.wicket.markup.html.WebPage$PageMapChecker

/*
* 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.Component;
import org.apache.wicket.IPageMap;
import org.apache.wicket.IRequestTarget;
import org.apache.wicket.Page;
import org.apache.wicket.PageMap;
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.ComponentTag;
import org.apache.wicket.markup.MarkupElement;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.TagUtils;
import org.apache.wicket.markup.html.internal.HtmlBodyContainer;
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.model.Model;
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.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.
* <p>
* 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
{
  /**
   * 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;

    /** The unload model for deleting the pagemap cookie */
    private Model onUnLoadModel;

    private final WebPage webPage;

    /**
     * Construct.
     *
     * @param webPage
     */
    PageMapChecker(WebPage webPage)
    {
      this.webPage = webPage;
    }

    /**
     * @see org.apache.wicket.markup.html.IHeaderContributor#renderHead(org.apache.wicket.Response)
     */
    public final void renderHead(final IHeaderResponse headResponse)
    {
      Response response = headResponse.getResponse();
      final WebRequestCycle cycle = (WebRequestCycle)RequestCycle.get();
      final IRequestTarget target = cycle.getRequestTarget();

      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.PageMapAccessMetaData)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(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 intermangle 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!='" +
                name + "')) { window.location=\"");
        response.write(url);
        response.write("\"; }");
        JavascriptUtils.writeCloseTag(response);
      }
    }
  }

  /** log. */
  private static final Logger _log = LoggerFactory.getLogger(WebPage.class);

  /** The resource references used for new window/tab support */
  private static ResourceReference cookiesResource = new ResourceReference(WebPage.class,
      "cookies.js");

  private static final long serialVersionUID = 1L;

  /**
   * Boolean flag that represents whether or not we have already added a
   * {@link HtmlBodyContainer} to this page or not
   */
  private boolean bodyContainerAdded = false;

  /**
   * 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(PageMap)
   */
  protected WebPage(final IPageMap pageMap)
  {
    super(pageMap);
    commonInit();
  }

  /**
   * @see Page#Page(PageMap, 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.
   *
   * @param parameters
   *            Wrapped query string parameters.
   */
  protected WebPage(final PageParameters parameters)
  {
    super(parameters);
  }

  /**
   * 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
   */
  public String getMarkupType()
  {
    return "html";
  }

  /**
   * This method is called when the compressing coding and response stategies
   * are configured in your Application object like this:
   *
   * <pre>
   * protected IRequestCycleProcessor newRequestCycleProcessor()
   * {
   *   return new UrlCompressingWebRequestProcessor();
   * }
   * </pre>
   *
   * @return The URLCompressor for this webpage.
   *
   * @since 1.2
   *
   * @see UrlCompressingWebRequestProcessor
   * @see UrlCompressor
   */
  public final UrlCompressor getUrlCompressor()
  {
    if (compressor == null)
    {
      compressor = new UrlCompressor();
    }
    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()
   */
  protected void configureResponse()
  {
    super.configureResponse();

    if (getWebRequestCycle().getResponse() instanceof WebResponse) {
      final WebResponse response = getWebRequestCycle().getWebResponse();
      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());
  }

  protected void onBeforeRender()
  {
    super.onBeforeRender();

    if (!bodyContainerAdded)
    {
      // Add a Body container if the associated markup contains a <body>
      // tag get markup stream gracefully
      MarkupStream markupStream = getAssociatedMarkupStream(false);
      if (markupStream != null)
      {
        // The default <body> container. It can be accessed, replaced
        // and attribute modifiers can be attached. <body> tags without
        // wicket:id get automatically a wicket:id="body" assigned.
        // find the body tag
        while (markupStream.hasMore())
        {
          final MarkupElement element = markupStream.next();
          if (element instanceof ComponentTag)
          {
            final ComponentTag tag = (ComponentTag)element;
            if (tag.isOpen() && TagUtils.isBodyTag(tag))
            {
              // Add a default container if the tag has the
              // default name
              if (HtmlBodyContainer.BODY_ID.equals(tag.getId()))
              {
                add(new HtmlBodyContainer(tag.getId()));
              }
              bodyContainerAdded = true;
              break;
            }
          }
        }
      }
    }

  }

  /**
   *
   * @see org.apache.wicket.Component#onDetach()
   */
  protected void onDetach()
  {
    // This code can not go into HtmlHeaderContainer as
    // header.onEndRequest() is executed inside an iterator
    // and you can only call container.remove() which
    // is != iter.remove(). And the iterator is not available
    // inside onEndRequest(). Obviously WebPage.onEndRequest()
    // is invoked outside the iterator loop.
    final Component header = get(HtmlHeaderSectionHandler.HEADER_ID);
    if (header != null)
    {
      this.remove(header);
    }
    super.onDetach();
  }
}
TOP

Related Classes of org.apache.wicket.markup.html.WebPage$PageMapChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.