001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.markup.html.link; 018 019import org.apache.wicket.IRequestListener; 020import org.apache.wicket.Page; 021import org.apache.wicket.core.request.handler.IPageProvider; 022import org.apache.wicket.core.request.handler.PageProvider; 023import org.apache.wicket.markup.ComponentTag; 024import org.apache.wicket.markup.html.WebMarkupContainer; 025import org.apache.wicket.request.mapper.parameter.PageParameters; 026 027/** 028 * Implementation of an <a href="http://www.w3.org/TR/REC-html40/present/frames.html#h-16.5">inline 029 * frame</a> component. Must be used with an iframe (<iframe src...) element. The src attribute 030 * will be generated. 031 * 032 * @author Sven Meier 033 * @author Ralf Ebert 034 * 035 */ 036 037public class InlineFrame extends WebMarkupContainer implements IRequestListener 038{ 039 private static final long serialVersionUID = 1L; 040 041 /** The provider of the page. */ 042 private final IPageProvider pageProvider; 043 044 /** 045 * Constructs an inline frame that instantiates the given Page class when the content of the 046 * inline frame is requested. The instantiated Page is used to render a response to the user. 047 * 048 * @param <C> 049 * 050 * @param id 051 * See Component 052 * @param c 053 * Page class 054 */ 055 public <C extends Page> InlineFrame(final String id, final Class<C> c) 056 { 057 this(id, c, null); 058 } 059 060 /** 061 * Constructs an inline frame that instantiates the given Page class when the content of the 062 * inline frame is requested. The instantiated Page is used to render a response to the user. 063 * 064 * @param <C> 065 * 066 * @param id 067 * See Component 068 * @param c 069 * Page class 070 * @param params 071 * Page parameters 072 */ 073 public <C extends Page> InlineFrame(final String id, final Class<C> c, 074 final PageParameters params) 075 { 076 this(id, new PageProvider(c, params)); 077 078 // Ensure that c is a subclass of Page 079 if (!Page.class.isAssignableFrom(c)) 080 { 081 throw new IllegalArgumentException("Class " + c + " is not a subclass of Page"); 082 } 083 } 084 085 /** 086 * This constructor is ideal if a Page object was passed in from a previous Page. Construct an 087 * inline frame containing the given Page. 088 * 089 * @param id 090 * See component 091 * @param page 092 * The page 093 */ 094 public InlineFrame(final String id, final Page page) 095 { 096 this(id, new PageProvider(page.getPageId(), page.getClass(), page.getRenderCount())); 097 } 098 099 /** 100 * This constructor is ideal for constructing pages lazily. 101 * 102 * Constructs an inline frame which invokes the getPage() method of the IPageLink interface when 103 * the content of the inline frame is requested. Whatever Page objects is returned by this 104 * method will be rendered back to the user. 105 * 106 * @param id 107 * See Component 108 * @param pageProvider 109 * the provider of the page to be contained in the inline frame if and when the 110 * content is requested 111 */ 112 public InlineFrame(final String id, IPageProvider pageProvider) 113 { 114 super(id); 115 116 this.pageProvider = pageProvider; 117 } 118 119 /** 120 * Gets the url to use for this link. 121 * 122 * @return The URL that this link links to 123 */ 124 protected CharSequence getURL() 125 { 126 return urlForListener(new PageParameters()); 127 } 128 129 /** 130 * Handles this frame's tag. 131 * 132 * @param tag 133 * the component tag 134 * @see org.apache.wicket.Component#onComponentTag(ComponentTag) 135 */ 136 @Override 137 protected void onComponentTag(final ComponentTag tag) 138 { 139 checkComponentTag(tag, "iframe"); 140 141 // Set href to link to this frame's frameRequested method 142 CharSequence url = getURL(); 143 144 // generate the src attribute 145 tag.put("src", url); 146 147 super.onComponentTag(tag); 148 } 149 150 @Override 151 public boolean rendersPage() 152 { 153 return false; 154 } 155 156 @Override 157 public final void onRequest() 158 { 159 setResponsePage(pageProvider.getPageInstance()); 160 } 161 162 163 @Override 164 protected boolean getStatelessHint() 165 { 166 /* 167 * TODO optimization: the inlineframe component does not always have to be stateless. 168 * 169 * unfortunately due to current implementation of using a ILinkListener 170 * callback it has to always be stateful because it can be put inside a ListView item which 171 * will not be built upon a stateless callback causing a "component at path 172 * listview:0:iframe not found" error. 173 * 174 * eventually variant such as (string, ipagemap, class<? extends Page>) can be made 175 * stateless because they can generate a bookmarkable url. another advantage of a 176 * bookmarkable url is that multiple iframes will not block. 177 */ 178 return false; 179 } 180}