/*******************************************************************************
* Copyright (c) 2002, 2010 Innoopract Informationssysteme GmbH.
* 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
******************************************************************************/
package org.eclipse.rwt.internal.service;
import java.io.*;
import java.text.MessageFormat;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.eclipse.rwt.SessionSingletonBase;
import org.eclipse.rwt.internal.RWTMessages;
import org.eclipse.rwt.internal.lifecycle.*;
import org.eclipse.rwt.internal.protocol.JsonMessageWriter;
import org.eclipse.rwt.internal.protocol.ProtocolMessageWriter;
import org.eclipse.rwt.internal.util.HTML;
import org.eclipse.rwt.service.ISessionStore;
public class LifeCycleServiceHandler extends AbstractServiceHandler {
public static final String RWT_INITIALIZE = "rwt_initialize";
// TODO [if]: Move this code to a fragment
private static final String PATTERN_RELOAD
= "qx.core.Init.getInstance().getApplication().reload( \"{0}\" )";
final static String SESSION_INITIALIZED
= LifeCycleServiceHandler.class.getName() + "#isSessionInitialized";
private static StringWriter wrappedWriter;
public void service() throws IOException, ServletException {
synchronized( ContextProvider.getSession() ) {
synchronizedService();
}
}
void synchronizedService() throws ServletException, IOException {
initializeStateInfo();
RWTRequestVersionControl.beforeService();
try {
if( RWTRequestVersionControl.isValid()
|| LifeCycleServiceHandler.isSessionRestart()
|| ContextProvider.getRequest().getSession().isNew() )
{
runLifeCycle();
} else {
handleInvalidRequestCounter();
}
} finally {
RWTRequestVersionControl.afterService();
}
}
private static void runLifeCycle() throws ServletException, IOException {
checkRequest();
initializeSession();
if( isSessionInitialized() ) {
RequestParameterBuffer.merge();
LifeCycle lifeCycle = ( LifeCycle )LifeCycleFactory.getLifeCycle();
lifeCycle.execute();
} else {
Map parameters = ContextProvider.getRequest().getParameterMap();
RequestParameterBuffer.store( parameters );
StartupPage.send();
}
writeOutput();
}
//////////////////
// helping methods
private static boolean isSessionRestart() {
HttpServletRequest request = getRequest();
boolean startup = request.getParameter( RequestParams.STARTUP ) != null;
String uiRoot = request.getParameter( RequestParams.UIROOT );
HttpSession session = request.getSession();
return !session.isNew() && !startup && uiRoot == null
|| startup && isSessionInitialized();
}
private static void initializeStateInfo() {
if( ContextProvider.getStateInfo() == null ) {
IServiceStateInfo stateInfo = new ServiceStateInfo();
ContextProvider.getContext().setStateInfo( stateInfo );
}
if( ContextProvider.getStateInfo().getResponseWriter() == null ) {
HtmlResponseWriter htmlResponseWriter = new HtmlResponseWriter();
ContextProvider.getStateInfo().setResponseWriter( htmlResponseWriter );
}
// [hs] patched for protocol
if( ContextProvider.getStateInfo().getProtocolMessageWriter() == null ) {
wrappedWriter = new StringWriter();
ProtocolMessageWriter writer
= new JsonMessageWriter( new PrintWriter( wrappedWriter ) );
wrappedWriter.write( "###BEGIN_JSON###\n" );
ContextProvider.getStateInfo().setProtocolMessageWriter( writer );
}
}
private static void handleInvalidRequestCounter()
throws IOException
{
IServiceStateInfo stateInfo = ContextProvider.getStateInfo();
HtmlResponseWriter out = stateInfo.getResponseWriter();
String message = RWTMessages.getMessage( "RWT_MultipleInstancesError" );
Object[] args = new Object[] { message };
// Note: [rst] Do not use writeText as umlauts must not be encoded here
out.write( MessageFormat.format( PATTERN_RELOAD, args ) );
HttpServletResponse response = ContextProvider.getResponse();
response.setContentType( HTML.CONTENT_TEXT_JAVASCRIPT_UTF_8 );
LifeCycleServiceHandler.writeOutput();
}
private static boolean isSessionInitialized() {
ISessionStore session = ContextProvider.getSession();
return Boolean.TRUE.equals( session.getAttribute( SESSION_INITIALIZED ) );
}
public static void initializeSession() {
if( !isSessionInitialized() ) {
if( getRequest().getParameter( RWT_INITIALIZE ) != null ) {
ISessionStore session = ContextProvider.getSession();
session.setAttribute( SESSION_INITIALIZED, Boolean.TRUE );
}
}
}
private static void checkRequest() {
if( isSessionRestart() ) {
clearSessionStore();
}
}
private static void clearSessionStore() {
SessionStoreImpl sessionStore
= ( SessionStoreImpl )ContextProvider.getSession();
// clear attributes of session store to enable new startup
sessionStore.valueUnbound( null );
// reinitialize session store state
sessionStore.valueBound( null );
sessionStore.setAttribute( SessionSingletonBase.LOCK, new Object() );
}
public static void writeOutput() throws IOException {
if( !ContextProvider.getContext().isDisposed() ) {
HtmlResponseWriter content
= ContextProvider.getStateInfo().getResponseWriter();
PrintWriter out = getOutputWriter();
ProtocolMessageWriter protocolMessageWriter
= ContextProvider.getStateInfo().getProtocolMessageWriter();
if( protocolMessageWriter.isStarted() ) {
protocolMessageWriter.finish();
wrappedWriter.write( "\n###END_JSON###\n" );
wrappedWriter.flush();
appendProtocolToOutWriter( out );
}
try {
// send the body to the client
for( int i = 0; i < content.getBodySize(); i++ ) {
out.print( content.getBodyToken( i ) );
}
} finally {
out.close();
}
}
}
private static void appendProtocolToOutWriter( final PrintWriter out ) {
StringBuffer buffer = wrappedWriter.getBuffer();
out.print( buffer.toString() );
}
}