/******************************************************************************* * Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development * Frank Appel - replaced singletons and static fields (Bug 337787) ******************************************************************************/ package org.eclipse.rap.rwt.internal.service; import static org.eclipse.rap.rwt.internal.RWTMessages.getMessage; import static org.eclipse.rap.rwt.internal.service.ContextProvider.getRequest; import static org.eclipse.rap.rwt.internal.theme.ThemeUtil.getCssValue; import static org.eclipse.rap.rwt.internal.theme.ThemeUtil.getThemeIdFor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.eclipse.rap.rwt.client.WebClient; import org.eclipse.rap.rwt.internal.RWTMessages; import org.eclipse.rap.rwt.internal.application.ApplicationContextImpl; import org.eclipse.rap.rwt.internal.lifecycle.EntryPointManager; import org.eclipse.rap.rwt.internal.service.StartupPageTemplate.VariableWriter; import org.eclipse.rap.rwt.internal.theme.CssImage; import org.eclipse.rap.rwt.internal.theme.SimpleSelector; import org.eclipse.rap.rwt.internal.util.HTTP; public class StartupPage { private final ApplicationContextImpl applicationContext; private final List<String> jsLibraries; private String clientJsLibrary; StartupPageTemplate startupPageTemplate; public StartupPage( ApplicationContextImpl applicationContext ) { this.applicationContext = applicationContext; jsLibraries = new ArrayList<>(); } public void activate() { startupPageTemplate = new StartupPageTemplate(); } public void deactivate() { startupPageTemplate = null; } public void setClientJsLibrary( String location ) { clientJsLibrary = location; } public void addJsLibrary( String location ) { jsLibraries.add( location ); } public void send( HttpServletResponse response ) throws IOException { setResponseHeaders( response ); startupPageTemplate.writePage( response.getWriter(), new StartupPageValueProvider() ); } static void setResponseHeaders( HttpServletResponse response ) { response.setContentType( HTTP.CONTENT_TYPE_HTML ); response.setCharacterEncoding( HTTP.CHARSET_UTF_8 ); // TODO [rh] this is a preliminary fix for a behavior that was easily // reproducible in IE but also happened in FF: when restarting a // web app (hit return in location bar), the browser used a cached // version of the index.html *without* sending a request to ask // whether the cached page can be used. // fix for bug 220733: append no-store to the Cache-Control header response.addHeader( "Cache-Control", "max-age=0, no-cache, must-revalidate, no-store" ); response.setHeader( "Pragma", "no-cache" ); response.setDateHeader( "Expires", 0 ); } protected void writeTitle( PrintWriter printWriter ) { writeEntryPointProperty( printWriter, WebClient.PAGE_TITLE ); } protected void writeBody( PrintWriter printWriter ) { writeEntryPointProperty( printWriter, WebClient.BODY_HTML ); } protected void writeHead( PrintWriter printWriter ) { Map<String, String> properties = getCurrentEntryPointProperties(); String favIcon = properties.get( WebClient.FAVICON ); if( favIcon != null && favIcon.length() > 0 ) { String pattern = "<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"%1$s\" />"; String favIocnMarkup = String.format( pattern, getResourceLocation( favIcon ) ); printWriter.write( favIocnMarkup ); } writeEntryPointProperty( printWriter, WebClient.HEAD_HTML ); } private void writeLibraries( PrintWriter printWriter ) { writeScriptTag( printWriter, clientJsLibrary ); for( String location : jsLibraries ) { writeScriptTag( printWriter, location ); } } protected void writeScriptTag( PrintWriter printWriter, String libraryLocation ) { if( libraryLocation != null ) { printWriter.write( " <script type=\"text/javascript\" src=\"" ); printWriter.write( libraryLocation ); printWriter.write( "\" charset=\"" ); printWriter.write( HTTP.CHARSET_UTF_8 ); printWriter.write( "\"></script>\n" ); } } protected void writeBackgroundImage( PrintWriter printWriter ) { printWriter.write( getBackgroundImageLocation() ); } protected void writeNoScriptMessage( PrintWriter printWriter ) { String message = getMessage( RWTMessages.NO_SCRIPT_WARNING, getRequest().getLocale() ); printWriter.write( message ); } protected void writeAppScript( PrintWriter printWriter ) { StringBuilder code = new StringBuilder(); code.append( "rwt.remote.MessageProcessor.processMessage( " ); code.append( StartupJson.get() ); code.append( ");" ); printWriter.write( code.toString() ); } protected String getBackgroundImageLocation() { String resourceName = getBrackgroundImage().getResourcePath( applicationContext ); return resourceName != null ? getResourceLocation( resourceName ) : ""; } protected CssImage getBrackgroundImage() { String servletPath = getRequest().getServletPath(); return ( CssImage )getCssValue( getThemeIdFor( servletPath ), "Display", "background-image", SimpleSelector.DEFAULT, null ); } private Map<String, String> getCurrentEntryPointProperties() { EntryPointManager entryPointManager = applicationContext.getEntryPointManager(); return entryPointManager.getEntryPointRegistration( getRequest() ).getProperties(); } private String getResourceLocation( String resourceName ) { return applicationContext.getResourceManager().getLocation( resourceName ); } private void writeEntryPointProperty( PrintWriter printWriter, String property ) { String title = getCurrentEntryPointProperties().get( property ); if( title != null ) { printWriter.write( title ); } } private class StartupPageValueProvider implements VariableWriter { @Override public void writeVariable( PrintWriter printWriter, String variableName ) { if( variableName.equals( StartupPageTemplate.TOKEN_LIBRARIES ) ) { writeLibraries( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_TITLE ) ) { writeTitle( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_BODY ) ) { writeBody( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_HEADERS ) ) { writeHead( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_BACKGROUND_IMAGE ) ) { writeBackgroundImage( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_NO_SCRIPT_MESSAGE ) ) { writeNoScriptMessage( printWriter ); } else if( variableName.equals( StartupPageTemplate.TOKEN_APP_SCRIPT ) ) { writeAppScript( printWriter ); } else { throw new IllegalArgumentException( "Unsupported variable: " + variableName ); } } } }