package votorola.a.web.wic; // Copyright 2008-2012, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE. import javax.servlet.http.*; import org.apache.wicket.*; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.MarkupType; import org.apache.wicket.markup.html.IHeaderResponse; import org.apache.wicket.markup.html.basic.*; import org.apache.wicket.markup.html.form.*; import org.apache.wicket.markup.html.navigation.paging.*; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.request.http.WebResponse; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.model.*; import org.apache.wicket.util.time.Duration; import votorola.a.*; import votorola.a.web.wic.authen.*; import votorola.a.voter.*; import votorola.g.lang.*; import votorola.g.web.*; import votorola.g.web.wic.*; /** An HTML page in the Wicket web interface. The page defines the following JavaScript * variables for the use of client scripts: * *
Name | *Value | *
---|---|
voc.pageJClass | * *The class name of the specific Java type that implements this page. The * name is fully qualified. | * *
Cacheable pages may depend on the user's login state. A {@linkplain * #addSessionStateCookie(String,String,WebResponse) cookie/script mechanism} is used * to automatically reload cached pages and bypass the cache following any change to * login state. The rendering of the page may therefore depend on the identity of * the authenticated user, but not on any other crucial variable that might change over * the course of the cache duration.
* * @see #setCacheable(boolean) * @see #getCacheDuration() */ protected final boolean isCacheable() { return isCacheable; } private boolean isCacheable; /** Sets whether client-side caching is enabled. * * @see #isCacheable() */ protected final void setCacheable( final boolean is ) { isCacheable = is; } /** Constructs a label containing a non-breaking space character ( ). */ public static Label newLabelNBSP( String id ) { final Label label = new Label( id, " " ); label.setEscapeModelStrings( false ); return label; } /** Constructs a label containing a non-breaking space character, for situations that * preclude using a proper null component. One such situation is the end of the * page, where a null component somehow causes clipping of the content above (IE7). */ public static Component newNullComponentAsLabel( String id ) { return newLabelNBSP( id ); } /** Constructs a paging navigator with a standard configuration. */ public static PagingNavigator newPagingNavigator( final String id, final DataView> dataView ) { final PagingNavigator navigator = new PagingNavigator( id, dataView ) // navigator.getPagingNavigation().setViewSize( 5 ); //// getPagingNavigation() is null till after onBeforeRender() (since upgrade from 1.3.2 to 1.3.7) { protected PagingNavigation newNavigation( final String idPN, final IPageable pageable, final IPagingLabelProvider labelProvider ) { final PagingNavigation pN = super.newNavigation( idPN, pageable, labelProvider ); pN.setViewSize( 5 ); // page link short cuts, at a time (rather than default 10) return pN; } }; return navigator; } // - I - H e a d e r - C o n t r i b u t o r ------------------------------------------ public @Override void renderHead( final IHeaderResponse r ) { assert MarkupType.HTML_MARKUP_TYPE.equals( getMarkupType() ); final VRequestCycle cycle = VRequestCycle.get(); final WebRequest reqW = cycle.vRequest(); final String contextPath = reqW.getContextPath(); // Define JavaScript variables for general use on client side ... // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - final StringBuilder b = new StringBuilder(); b.append( "var voc =" // namespace for public, client-side variables + "{" ); b.append( "pageJClass:'" ).append( getClass().getName() ).append( '\'' ); // ... and specifically for use in VPageHTML.js. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - final String state; b.append( ",contextPath:'" ).append( contextPath ).append( '\'' ); if( isCacheable ) { final VSession.User user = VSession.get().user(); state = encodeSessionStateCookieValue( user ); final Cookie cookie = reqW.getCookie( COOKIE_SESSION_STATE ); if( cookie != null && "refreshing".equals(cookie.getValue()) ) { // clear the loop guard, per VPageHTML.js addSessionStateCookie( state, contextPath, cycle.vResponse() ); } final Authenticator authenticator = VOWicket.get().authenticator(); if( authenticator instanceof WikiAuthenticator ) { if( user != null && user.isPersistent() ) b.append( ",isPersistentLogin:true" ); b.append( ",pollwikiCookiePrefix:'" ).append( ((WikiAuthenticator)authenticator).getCookiePrefix() ).append( '\'' ); } } else state = "ignore"; // tell VPageHTML.js not to bother synchronizing this page b.append( ",sessionState:'" ).append( state ).append( '\'' ); b.append( "};" ); r.renderJavaScript( b.toString(), /*unique ID for rendering*/VPageHTML.class.getName() ); // Inject VPageHTML.js ASAP, because it may force a reload of the page. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - r.renderJavaScriptReference( cycle.staticContextLocation() + "/web/VPageHTML.js" ); // Ensure Wicket provides its Mootools-like extended 'domready' event. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - r.renderOnDomReadyJavaScript( "/* forcing inclusion of wicket-event.js */" ); // resources/org.apache.wicket.markup.html.WicketEventReference/wicket-event.js // Add a page icon. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - r.renderString( "\n" // + "\n" /// fails, I get an IE default logo ); // - - - final String htmlHeaderInsert = vApplication().htmlHeaderInsert(); if( htmlHeaderInsert != null ) r.renderString( htmlHeaderInsert ); } // - W e b - P a g e ------------------------------------------------------------------ /** Sets headers to enable or disable caching. * * @see #isCacheable() */ protected @Override final void setHeaders( final WebResponse r ) { if( isCacheable ) { r.enableCaching( cacheDuration, WebResponse.CacheScope.PRIVATE ); // This alone does not enable caching. As noted in WebResponseX, we must also // avoid calling super.setHeaders(r). } else super.setHeaders( r ); // disables caching, as documented } }